6. Cấu trúc của luận văn
2.3.3. Thuật toán cập nhật gia tăng khung nhìn thực với truy vấn nối trong
trong
2.3.3.1. Truy vấn SPJ (Select – Project – Join)
Truy vấn SPJ là truy vấn chỉ bao gồm các mệnh đề SELECT, FROM, WHERE, nhưng không bao gồm các chức năng nhóm và tổng hợp. Từ mệnh đề có thể chứa các kết nối bên trong. Đối với trường hợp SPJ KNT, đã xây dựng một chương trình tạo mã kích hoạt thực hiện cập nhật gia tăng dựa trên thuật toán đã cải tiến các bản phát hành trước đó [13] và tạo phần mềm của nó cho tổng hợp tự động của mã nguồn kích hoạt để cập nhật gia tăng KNT xem xét rằng:
- Kết quả truy vấn có thể chứa trùng lặp;
- Bất kỳ một khóa của mỗi BG được thêm tự động vào mệnh đề SELECT;
- Xem xét hoạt động sửa đổi dưới dạng các hoạt động tương đương như xóa và chèn tiếp;
- Loại trừ thao tác dữ liệu trong BG không ảnh hưởng đến KNT; KNT kiểu SPJ là KNT được tạo ra trên cơ sở truy vấn SPJ – truy vấn chỉ chứa các phép chọn, chiếu và nối; kết quả thực thi các truy vấn có thể chứa các bản ghi trùng lặp, nhưng không bao gồm các phép toán thống kê (SUM, COUNT, AVG, MIN, MAX…). Truy vấn tạo KNT kiểu SPJ với truy vấn gốc:
SELECT <danh sách cột>
FROM <table_1> INNER JOIN <table_2> ON <điều kiện nối> INNER JOIN <table_3> ON <điều kiện nối>…
WHERE <điều kiện lọc> Trong đó
F: Mệnh đề FROM, tập các BG T1, T2…Tn được sử dụng trong truy vấn tạo KNT.
J: Tập hợp các điều kiện của các phép nối.
W: Mệnh đề WHERE, điều kiện chọn lựa bản ghi để xử lý.
Ti={𝑇𝑖|i=1, 2,..,n} – tập hợp các bảng gốc được sử dụng trong truy vấn.
Fins: Mệnh đề FROM trong trường hợp thêm bản ghi. Fdel: Mệnh đề FROM trong trường hợp xóa bản ghi.
Cứ mỗi khi dữ liệu trong các BG được cập nhật, các KNT sử dụng các dữ liệu đó trở nên không thực tiễn. Để duy trì các bảng KNT trong trạng thái thực tiễn (actual state), cần phải cập nhật chúng mỗi khi có sự thay đổi dữ liệu (insert, update, delete) trong các BG. Quá trình làm cho dữ liệu trong KNT tương ứng với dữ liệu trong các BG được gọi là sự thực tiễn hoá (actualization, cập nhật).
Tuỳ thuộc vào cách thức thực hiện, cập nhật được chia thành ba phương pháp chính, đó là cập nhật hoàn toàn (COMPLETE), cập nhật gia tăng (INCREMENTAL hay còn gọi là FAST) và ép buộc (FORCE). Cập nhật hoàn toàn thực tế là thực thi lại truy vấn trên cơ sở KNT đã được tạo ra và lưu kết quả vào KNT. CNGT chỉ thực hiện điều chỉnh phần dữ liệu trong KNT liên quan đến các sửa đổi dữ liệu trong các BG. Cập nhật ép buộc nghĩa là khi có khả năng thì thực hiện CNGT, còn nếu không thì sử dụng cập nhật hoàn toàn. Trong hầu hết các trường hợp có thể thực hiện CNGT đối với các KNT kiểu SPJ.
Chúng ta xét riêng rẽ ba trường hợp thêm mới, sửa đổi và xoá các bản ghi. Việc sửa đổi một bản ghi có thể xem là tương đương với nhóm hai hành động liên tiếp: xoá một bản ghi và sau đó thêm mới một bản ghi.
a. Trường hợp thêm mới các bản ghi
Giả sử tập hợp các bản ghi 𝑇𝑖𝑖𝑛𝑠được thêm vào BG 𝑇𝑖. Bước 1: Fins = T1 J T2 J …… d𝑇𝑖𝑖𝑛𝑠 J … Tn
Bước 2: 𝑑𝑄𝑖𝑖𝑛𝑠 = Select S from Fins where W Bước 3: Insert into MV Select 𝑑𝑄𝑖𝑖𝑛𝑠
b. Trường hợp xoá các bản ghi
Giả sử tập hợp các bản ghi 𝑇𝑖𝑑𝑒𝑙được xoá từ BG 𝑇𝑖. Bước 1: Fdel = T1 J T2 J …… d𝑇𝑖𝑑𝑒𝑙 J … Tn
Bước 2: 𝑑𝑄𝑖𝑑𝑒𝑙 = Select S from Fdel where W Bước 3: For each X in 𝑑𝑄𝑖𝑑𝑒𝑙:
Where MV. 𝐾𝑇1 (X) = 𝐾𝑇1 (X) And MV. 𝐾𝑇𝑖 (X) = 𝐾𝑇𝑖 (X) And MV. 𝐾𝑇𝑛 (X) = 𝐾𝑇𝑛 (X)
c. Trường hợp sửa đổi các bản ghi
Giả sử trong BG 𝑇𝑖 , tập hợp các bản ghi 𝑇𝑖𝑜𝑙𝑑 được thay đổi thành tập hợp 𝑇𝑖𝑛𝑒𝑤.
Dễ nhận thấy rằng, sửa đổi một bản ghi tương đương với xoá bỏ một bản ghi sau đó thêm mới một bản ghi khác. Đối với trường hợp tập hợp, cập nhật một tập hợp các bản ghi tương đương với xoá bỏ một tập hợp bản ghi, sau đó thêm mới một tập hợp bản ghi khác. Suy ra, trong trường hợp này có thể thực thi mục b và tiếp theo sau đó là mục a để CNGT KNT (update Ti = delete Tiold + insert Tinew), với 𝑇𝑖𝑑𝑒𝑙=𝑇𝑖𝑜𝑙𝑑 và
𝑇𝑖𝑖𝑛𝑠=𝑇𝑖𝑛𝑒𝑤tương ứng. Trong đó, mỗi bản ghi <𝑇𝑗𝑜𝑙𝑑𝑘 > tương ứng với một bản ghi <𝑇𝑗𝑛𝑒𝑤𝑘 >.
2.3.3.2. Truy vấn nối trong bao gồm các hàm thống kê
Thuật toán CNGT đồng bộ KNT trên cơ sở các truy vấn bao gồm phép nối trong được tham khảo từ công trình nghiên cứu [2], chủ yếu được tổng hợp và phát triển từ các nghiên cứu [6-11]. Thuật toán này chưa quan tâm đến KNT được tạo trên cơ sở truy vấn lồng, truy vấn đệ quy, truy vấn bao gồm phép nối ngoài. Giả sử KNT được tạo trên cơ sở truy vấn bao gồm các hàm thống kê Q (S, F, J, W, G). Trong đó:
S: Mệnh đề SELECT, tập các cột được lựa chọn. S có thể bao gồm các cột hoặc các hàm thống kê với biểu thức (E) trên các cột từ BG như SUM(E), COUNT(E), AVG(E), MIN(E) và MAX(E). E không chứa các hàm thống kê.
F: Mệnh đề FROM, tập các BG T1, T2…Tn được sử dụng trong truy vấn tạo KNT.
J: Tập hợp các điều kiện của các phép nối.
W: Mệnh đề WHERE, điều kiện chọn lựa bản ghi để xử lý. G: Mệnh đề GROUP BY, tập các cột gộp nhóm.
a. Tạo khung nhìn thực
Thông tin về cách thức biến đổi truy vấn để tạo KNT, cụ thể, thông tin về các cột trong bảng KNT giúp làm rõ các thuật toán cập nhật. Mục đích của việc biến đổi là để có thể sử dụng KNT tối ưu hơn và tối ưu hơn cả trong việc thực hiện CNGT KNT. S bao gồm các cột sẽ được lưu trong bảng KNT. Về các hàm thống kê, ta chỉ xem xét các trường hợp SUM(E), COUNT(E), AVG(E), MIN(E) và MAX(E). Từ quy định về cú pháp của lệnh truy vấn SELECT của ngôn ngữ SQL cũng như suy luận từ đại số quan hệ, có thể khẳng định, “cột” trong S có thể được hiểu là:
i) Một cột từ BG, hoặc là
ii) Biểu thức đại số trên các hàm thống kê, hoặc là
iii) Biểu thức đại số trên cột từ BG và hàm thống kê. Biểu thức (E) được đề cập không bao gồm hàm thống kê, nghĩa là không có trường hợp hàm thống kê là tham số của hàm thống kê. Với trường hợp iii), cột tham gia vào biểu thức một cách ngang hàng với hàm thống kê (chẳng hạn cột colA trong truy vấn: SELECT…, (colA + SUM(colB)) AS sumAB… GROUP BY …, colA), ta có thể xem xét như các cột bình thường khác tham gia vào G.
Vậy nên, thay vì lưu kết quả biểu thức đại số giữa các hàm thống kê hoặc hàm thống kê và cột, ta lưu kết quả thực thi của từng hàm thống kê. Vì vậy, nghiên cứu [2] đề xuất thực hiện một số biến đổi truy vấn trong quá trình tạo KNT:
- Tự động thêm COUNT(*) vì COUNT(*) giúp ta xác định khi nào
có thể xoá một bản ghi từ bảng KNT. Nếu không còn bản ghi nào tham gia vào nhóm, thì bản ghi cho nhóm cũng cần phải được xoá từ bảng KNT. Thật vậy, không có trường hợp nào trong số MAX, MIN, SUM giúp xác định điều đó, ngoài COUNT(*).
- Với trường hợp biểu thức đại số trên các hàm thống kê hoặc cột gộp nhóm (ii và iii), tách chúng ra và lưu thành các cột riêng lẻ. Khi
cần, ta có thể thực hiện tái tạo một cách rất đơn giản biểu thức ban đầu từ các cột được lưu trong KNT.
- Với trường hợp hàm AVG(E), đề xuất lưu riêng lẻ SUM(E) và COUNT(E), khi cần có thể tính một cách rất đơn giản, AVG(E) = SUM(E)/COUNT(E). Vậy, đề xuất chuyển AVG(E) thành SUM(E) và COUNT(E) trong truy vấn tạo KNT. Nếu E được xác định từ siêu dữ liệu là không thể NULL, thì COUNT(E) và COUNT(*) tương đương nhau. Khi đó, không cần lưu COUNT(E) mà chỉ cần lưu COUNT(*). Biến đổi W và J về dạng chuẩn tắc hội: (…OR…) AND…AND (…OR…). Việc biến đổi này nhằm hai mục đích, đó là i) so sánh mệnh đề W/J giữa các truy vấn và ii) xác định cập nhật trên BG có liên quan đến KNT hay không. i) Việc so sánh hai biểu thức luận lý là không hề đơn giản. Nghiên cứu [2] đề xuất so sánh hai biểu thức luận lý theo nguyên tắc chuyển về dạng chuẩn tắc hội, sau đó sắp xếp theo thứ tự từ điển và so sánh. ii) Ở dạng chuẩn tắc này, W/J chỉ cho giá trị TRUE nếu tất cả các mệnh đề cấu thành đều cho giá trị TRUE. Nếu một bản ghi nào đó không thoả một mệnh đề thành phần bất kỳ đều không có tác động đến kết quả thực thi truy vấn Q. Để đơn giản hoá, ta đưa vào các ký hiệu: C = W AND J.
b. Thuật toán cập nhật gia tăng
Sự kiện thay đổi dữ liệu trong các BG được chia theo ba loại thao tác: Thêm mới (insert), cập nhật (update) và xoá (delete) một tập các bản ghi. Nếu xét trên phương diện bản ghi của các bảng, thì các bản ghi là không trùng nhau. Tuy nhiên, nếu xét trên phương diện chỉ các bộ giá trị tương ứng với một tập các cột, thì các bộ giá trị này có thể trùng nhau. Ta gọi các “tập” này là các túi. Hầu hết các công trình liên quan CNGT KNT đã công bố trước đây xem trường hợp thao tác cập nhật (update) tương đương với việc xoá một túi các bản ghi và sau đó thêm mới một túi các bản ghi [2, 6]. Tuy nhiên, việc chia tách này không phải bao giờ cũng tốt hơn.
Trong trường hợp truy vấn không bao gồm các hàm thống kê MIN(E), MAX(E), ta có thể không cần phải phân tích update thành insert và
delete [2]. Trong trường hợp truy vấn bao gồm các hàm thống kê MIN(E), MAX(E), thì việc phân tích update thành insert và delete là tất nhiên, không có lựa chọn khác. Với insert, ta không cần quan tâm đến dữ liệu trong các BG, vì giá trị được thêm vào có thể thay thế giá trị MIN(E), MAX(E) hiện tại bằng cách so sánh với giá trị trong bảng KNT. Với delete, rõ ràng, nếu xoá bản ghi có giá trị trường đang là MIN(E) hoặc MAX(E), thì ta phải tìm lại giá trị MIN(E), MAX(E) mới từ các BG.
Trường hợp thao tác thứ nhất – thêm mới tập bản ghi dTinew vào bảng Ti
B1. Loại từ dTinew những bản ghi không thoả C. Tất nhiên, những bản ghi không thoả W không thể có tác động đến kết quả thực thi nên ta không cần thiết xét các bản ghi đó, có thể loại ngay từ đầu. Thường thì J chứa các điều kiện kiểu Ti.C1 = Tj.C2. Tuy nhiên, trong một số trường hợp, J có thể bao gồm cả điều kiện lọc thông thường với một vế là biểu thức đại số trên các cột từ một BG, còn vế thứ hai là một hằng số. Ở bước này, ta chỉ có thể lọc các bản ghi áp dụng các điều kiện trong C chỉ liên quan đến Ti. Việc loại bỏ các bản ghi ở bước này giúp giảm số lượng bản ghi tham gia vào phép nối ở B2.
B2. Nối tập dTinew thu được với các bảng còn lại trong F (ngoại trừ Ti), thu được kết quả dQi.
B3. Loại từ dQi các bản ghi không thoả C.
B4. Nhóm các bản ghi trong dQitheo G, chọn các cột tương ứng tham gia vào S, thực hiện các biểu thức cho mỗi nhóm theo G và cập nhật bảng KNT Tmv cho mỗi bản ghi thu được theo nguyên tắc:
- Nếu chưa có bản ghi dạng (G, S\G), thêm mới bản ghi.
- SUM(E) = SUM(E) + dSUMnew(E). Trong đó, E là biểu thức. dSUMnew(E) là SUM(E) trên dQi.
- COUNT(E) = COUNT(E) + dCOUNTnew(E). dCOUNTnew(E) là
- Nếu MIN(E) > dMINnew(E), nghĩa là bản ghi đang được thêm mới sẽ tạo nên giá trị MIN(E) cho nhóm, thì MIN(E) = dMINnew(E). Ngược lại, MIN(E) không thay đổi. dMINnew(E) là MIN(E) trên dQi. - Nếu MAX(E) < dMAXnew(E), nghĩa là bản ghi đang được thêm mới sẽ tạo nên giá trị MAX(E) mới cho nhóm, MAX(E)= dMAXnew(E). Ngược lại, MAX(E) không thay đổi. dMAXnew(E) là MAX(E) trên dQi.
- Thay vì lưu AVG(E), ta lưu SUM(E) và COUNT(E). Khi xuất hiện
truy vấn có AVG(E), ta tính AVG(E) từ SUM(E)/COUNT(E). Sự kiện delete tập bản ghi dTiold từ bảng Ti
B1. Loại từ dTiold những bản ghi không thoả C.
B2. Nối tập dTiold với các bảng còn lại, thu được kết quả dQi.
B3. Loại từ dQi các bản ghi không thoả C.
B4. Nhóm các bản ghi trong dQi theo G, chọn các cột tương ứng tham gia vào S, thực hiện các biểu thức cho mỗi nhóm theo G và cập nhật bảng KNT Tmv cho mỗi bản ghi thu được theo nguyên tắc:
- SUM(E) = SUM(E) - dSUMold(E). dSUMnew(E) là SUM(E) trên
dQi.
- COUNT(E) = COUNT(E) - dCOUNTold(E). dCOUNTold (E) là
COUNT(E) trên dQi.
- Nếu MIN(E) = dMINold(E), nghĩa là bản ghi đang được xoá tạo nên giá trị MIN(E) của nhóm, ta tính lại MIN(E) dựa trên các BG. Ngược lại, MIN(E) không thay đổi.
- Nếu MAX(E) = dMAXold(E), nghĩa là bản ghi đang được xoá tạo
nên giá trị MAX(E), ta tính lại MAX(E) dựa trên các BG. Ngược lại, MAX(E) không thay đổi.
- Nếu chỉ có COUNT(*) = 0, nghĩa là không còn bản ghi nào thuộc
nhóm tham gia vào kết quả truy vấn, xoá bản ghi dạng (G, S\G) từ Tmv.
Sự kiện update tập bản ghi dTi trong bảng Ti.
Khi phân tách sự kiện update thành hai sự kiện delete rồi sau đó là insert, có thể hiểu: Update dTi = delete dTiold + insert dTinew.
B1. So sánh dTiold và dTinew, loại khỏi dTiold và dTinew những bản ghi có điều chỉnh dữ liệu không liên quan đến Q.
B2. Thực hiện như trường hợp delete với dTiold. B3. Thực hiện như trường hợp insert với dTinew.
c. Một số cải tiến
Ngoài việc đề xuất thuật toán CNGT KNT dựa trên sự tổng hợp các công trình nghiên cứu trước đây, công trình [2] cũng có thực hiện một số cải tiến. Mô-đun sinh tự động mã nguồn trigger mà các tác giả dự kiến xây dựng sẽ sinh mã bao gồm việc thực hiện triển khai hai trong số các cải tiến đó.
Không xem xét tách update thành delete và insert
Như đã lý luận ở trên, nếu trong truy vấn chỉ bao gồm các hàm SUM(E) và COUNT(E), không xem xét trường hợp truy vấn có MIN(E) và MAX(E), còn AVG(E) thì được tính từ SUM(E) và COUNT(E), thì có thể không cần phân tách sự kiện update thành hai sự kiện insert và delete riêng biệt. Ta vẫn xem xét 2 tập: Tập tất cả các bản ghi với các giá trị mới (dTinew) và tập tất cả các bản ghi chứa giá trị cũ (dTiold). Các bước thực hiện CNGT như sau:
B1. Loại khỏi dTinew và dTiold các bản ghi không thoả C.
B2. Thực hiện phép nối ngoài đầy đủ giữa dTinew và dTiold với điều kiện nối trên một khoá của Ti và các cột của Ti tham gia vào G.
B3. Nhóm theo G tập các bản ghi trong kết quả phép nối các bảng còn lại với kết quả phép nối ngoài đầy đủ giữa dTinew và dTiold.
B4. Tính SUM(E) và COUNT(E) cho mỗi nhóm: dSUMnew(E), dSUMold(E), dCOUNTnew(E), dCOUNTold(E).
i) SUM(E) = SUM(E) + dSUMnew(E) – dSUMold(E).
ii) COUNT = COUNT(E) + dCOUNTnew(E) – dCOUNTold(E).
Với cách này, ta có thể chỉ gọi trigger một lần cho sự kiện update, thay vì 2 lần cho mỗi sự kiện insert và delete nếu phân tách update thành hai sự kiện riêng biệt. Việc nối các bảng cũng được thực hiện một lần. Thao tác cập nhật KNT cũng sẽ được thực hiện một lần cho mỗi nhóm, thay vì hai lần.
Một số cột tạo nên khoá (khoá chính và khoá độc nhất) của bảng Ti
tham gia vào G
Việc các cột nào đó có tạo nên khoá chính hay khoá nói chung hay không có thể được xác định thông qua siêu dữ liệu (meta-data) của CSDL. Nếu tất cả các cột tạo nên một khoá nào đó tham gia vào truy vấn – (Ci1, Ci2,… Cij,…, Cik), cụ thể là ở G, khi nối BG Ti với các bảng còn lại và sau đó thực hiện gộp nhóm theo G, thì bộ giá trị <Ci1, Ci2,…Cij,…, Cik> vẫn đại diện cho một bản ghi từ BG Ti. Vậy, khi cập nhật hoặc xoá một bản ghi từ Ti, ta có thể thực hiện như sau.
a) Sự kiện delete tập bản ghi dTiold từ BG Ti
B1. Loại từ dTiold những bản ghi không thoả C.
B2. Xoá từ Tmv các bản ghi thoả mãn điều kiện: dTiold.Cij = Tmv.Cij, với mọi Ci1, Ci2,…Cij,…, Cik.
b)Sự kiện update tập bản ghi dTiold trong BG Ti
Rõ ràng, một khi Ci1, Ci2,…Cij,…, Cik – những cột tạo nên khoá trong BG Ti tham gia vào G, thì có thể xảy ra hai trường hợp.
- Không có cột nào của Ti tham gia vào E trong COUNT(E), SUM(E), MIN(E) hoặc MAX(E)
B1. Loại từ dTiold những bản ghi không thoả C.
B2. Cập nhật Tmv, cập nhật bản ghi thoả mãn điều kiện: dTiold.Cij =