3.4.1.1 Giới thiệu
Các kỹ thuật xử lý truy vấn luôn luôn phải sử dụng chỉ số nhằm làm tăng tốc độ truy cập các cấu trúc dữ liệu. Đối với dữ liệu không gian, các truy vấn liên quan rất nhiều đến thao tác hình học với sự phức tạp cả về mức độ truy cập đĩa lẫn việc tính toán. Vì vậy, cần thiết phải lưu trữ dữ liệu không gian trong bộ nhớ thứ cấp được thiết kế phù hợp với các phương thức truy cập không gian (Spatial
Access Methods - SAMs). Thời gian thực hiện truy cập theo phương pháp mới ở
mức logarit của kích thước dữ liệu hoặc nhỏ hơn. Chỉ số sử dụng trong các SAM được gọi là chỉ số không gian.
Mỗi thao tác với một đối tượng không gian được thực hiện theo hai bước (hình 3.10). Bước thứ nhất là bước lọc, lựa chọn các đối tượng xấp xỉ thoả mãn điều kiện không gian. Có hai phép tính xấp xỉ đó là: Xấp xỉ liên tục và xấp xỉ lưới. Xấp xỉ liên tục trên cơ sở xác định hình chữ nhật nhỏ nhất bao nó (minimal
bounding box - mbb), với phép tính xấp xỉ lưới, không gian được phân chia
thành các ô bởi các lưới đều và giá trị của ADT được biểu diễn bởi tập các ô mà nó giao. Hình 3.11. minh họa hai cách tính xấp xỉ.
Hình 3.11. minh họa mbb và lưới xấp xỉ
Các đối tượng trong tập kết quả của bước lọc cần được tiếp tục xét trong bước thứ hai, bước làm tinh (refinement step). Từng đối tượng trong tập trên được duyệt và kiểm tra điều kiện không gian cho hình dạng thực của chúng. Quá
Lọc sơ cấp Lọc thứ cấp Tập dữ liệu đầu vào Dữ liệu đã lọc sơ cấp Kết quả Hình 3.10. Quy trình lọc dữ liệu Dữ liệu có mbr
thoả mãn yêu cầu truy vấn
trình này liên quan chặt chẽ với các thuật toán hình học. Phần này chỉ trình bày phương thức truy cập không gian trong bước lọc.
Trong phần lớn các hệ quản trị cơ sở dữ liệu, các phương thức tham chiếu phổ biến nhất sử dụng các B-tree và bảng băm nhằm đảm bảo số thao tác vào/ra dữ liệu tương ứng là logarit và hằng số của kích thước dữ liệu. Những thuộc tính của B-tree cho phép lập chỉ số dựa vào sự tồn tại một thứ tự của các giá trị khoá. Áp dụng kỹ thuật này cho dữ liệu không gian không phải vấn đề đơn giản. Cần sử dụng một nguyên tắc xây dựng khác, không dựa vào thứ tự trên tọa độ của các đối tượng. Có nhiều SAM thuộc một trong hai nhóm:
Các cấu trúc hướng không gian (space-driven structures): Dựa vào phân hoạch không gian hai chiều thành các ô, độc lập với phân bố của các đối tượng được ánh xạ đến các ô theo một số tiêu chí hình học.
Các cấu trúc hướng dữ liệu (data space-driven structures): được tổ chức theo phân hoạch các tập đối tượng.
Theo phương pháp thứ nhất, SAM được biểu diễn theo cấu trúc lưới (grid) và tuyến tính. Phương pháp thứ hai sử dụng R-tree, tương tự như B-tree, thích hợp với các thao tác cấu trúc lại, phân bố không chuẩn. Hai biến thể của R-tree là R*tree và R+tree.
3.4.1.2 Thiết kế phương thức truy cập không gian
Quá trình thiết kế phải đảm bảo các vấn đề sau: Kích thước dữ liệu lớn hơn không gian nhớ chính. Thời gian truy cập đĩa lâu hơn truy cập bộ nhớ chính.
Các đối tượng được nhóm trong các trang bộ nhớ (thường có kích thước từ 1Kb đến 4Kb). Ghi/đọc một trang vào/từ đĩa được xem như một thao tác vào/ra.
Khi mỗi trang được nạp vào bộ nhớ chính, nó sẵn sàng cho việc truy vấn cho đến khi bộ nhớ được dùng để nạp trang khác. Khi truy cập một đối tượng, có thể xảy ra hai trường hợp: Hoặc trang chứa đối tượng đã được nạp trong bộ nhớ chính hoặc gặp lỗi (page fault) và trang đó cần được nạp lại.
Với các giải thiết nêu trên thì SAM cần đạt được các yêu cầu sau:
Độ phức tạp thời gian là phân tuyến tính với các thao tác định vị điểm và tìm kiếm theo khoảng (hay theo cửa sổ),
Độ phức tạp không gian: So sánh được với độ phức tạp không gian của dữ liệu,
Yêu cầu quan trọng khác là tính linh động, SAM cần hỗ trợ việc chèn, xoá các đối tượng và thích nghi với sự tăng/giảm kích thước dữ liệu mà không làm giảm hiệu suất. Đây là một yêu cầu rất khó khi kích thước dữ liệu lớn. Tuy nhiên, trong thực tế, kích thước dữ liệu thường được biết trước, ít có sự thay đổi do đó yêu cầu cấu trúc thích nghi với sự thay đổi này tuy quan trọng nhưng là không cần thiết. Vì vậy, một cấu trúc hiệu quả có thể chỉ cần hỗ trợ quá trình xây dựng cấu trúc đó từ một tập dữ liệu có kích thước không đổi.
3.4.1.3 Cấu trúc hướng không gian
Grid file được thiết kế nhằm hỗ trợ việc lập chỉ số các đối tượng trên các
giá trị của một vài thuộc tính nào đó. Chỉ số ở đây là chỉ số nhiều khoá
(multikey index) cho phép truy vấn trên nhiều thuộc tính.
Cấu trúc tuyến tính là sự kết hợp B+tree và các hệ quản trị cơ sở dữ liệu, kỹ thuật này đã được sử dụng trong nhiều hệ quản trị cơ sở dữ liệu quan hệ mở rộng cho dữ liệu không gian, như Oracle [2].
Lưới cố định
Không gian tìm kiếm được phân rã thành nx x ny ô lưới chữ nhật có kích thước bằng nhau, các cell. Mỗi cell liên kết với một trang bộ nhớ. Một điểm P
được gán với cell c khi hình chữ nhật c.rect của cell này chứa P bên trong nó.
Các đối tượng bên trong một cell được được sắp xếp tuần tự trong trang bộ nhớ tương ứng.
Như vậy, không gian tìm kiếm được biểu diễn bởi một mảng 2 chiều
DIR[1..nx, 1..ny], trong đó phần tử DIR[i, j] chứa địa chỉ pageID của trang chứa
các đối tượng nằm trong cell ci, j. Các thao tác trên các đối tượng nằm trong không gian này được thực hiện dựa vào toạ độ của các đối tượng, từ đó xác định
cell chứa đối tượng, qua phần tử trong mảng DIR tương ứng để truy cập đến
Giải pháp lưới cố định phụ thuộc vào số lượng N các đối tượng được đánh chỉ mục. Nếu dung lượng 1 trang là M điểm thì có thể tạo lưới ít nhất N/M ô, mỗi ô nhiều nhất là M đối tượng, nếu quá số lượng này dẫn đến tràn và phải phân chia lại trang. Việc phân chia lại trang được minh họa như hình 3.13 khi thêm o dẫn đến phải phân lại trang.
Hình 3.13. Phân lại trang
Directory ny nx [a,b,c,d] [k,l,m,n] … … Trang tràn … [o] … xo x1 x2 x3 y1 y2 y3 y4 x4 yo y x a b d c l k m n o ny nx [a,b] [k,l] … … Trang Hình 3.12 Lưới cố định Directory
Cây tứ phân (quadtree)
Cây tứ phân là phương pháp biểu diễn dữ liệu nằm trong một vùng thông qua các ô phần tư (quadrant) của vùng đó và của các ô con bên trong nó (mức thấp hơn). Các ô này được đặt tên theo vị trí tương đối của chúng so với tâm của vùng: NW (tây-bắc), NE (đông-bắc), SW (tây-nam) và SE (đông-nam). Quá trình phân chia không gian tìm kiếm kết thúc khi số đối tượng phủ mỗi ô nhỏ hơn dung lượng trang nhớ. Trong hình 3.14, các ô được gán nhãn theo tên của các đối tượng nằm trong nó, dung lượng trang bộ nhớ là 4 đơn vị.
Theo cách biểu diễn này, bài toán truy vấn điểm được thực hiện một cách đơn giản bởi việc xác định một đường dẫn bắt đầu từ gốc, tại mỗi mức, cần xác định nút con chứa điểm đó. Bài toán truy vấn cửa sổ sẽ có độ phức tạp cao hơn, cần xác định tất cả các lá của cây có giao với cửa sổ truy vấn.
Khi bổ sung phần tử mới vào cây, có thể có nhiều hơn một lá sẽ được chèn phần tử này (vì một phần tử có thể phủ lên các vùng thuộc các lá khác nhau).
1 2 5 14 6 3 7 4 11 13 12 8 10 9 a b c d x y z t [1,2,5,6] [5,6,14] [2,3,6] [6] [8,11,12,13] [3,4,7] [9,10,13] Hình 3.14. Cây tứ phân R R a b c d x y z t
Mỗi lá như thế tương ứng với một đường dẫn xuất phát từ gốc. Việc chèn phần tử vào một lá có thể xảy ra hai trường hợp: hoặc dung lượng của lá chưa đạt đến giới hạn trang nhớ hoặc lá bị đã đầy trước khi chèn. Trong trường hợp thứ hai, cần phân chia lá thành hai lá mới.
Phương pháp sử dụng cây tứ phân có nhiều điểm hạn chế cho việc đáp ứng các yêu cầu của một phương thức truy cập không gian. Vì số lượng con của mỗi nút (node fan-out) bị giới hạn là 4, nó chỉ chiếm một phần nhỏ trang bộ nhớ, do đó việc ánh xạ một cây tứ phân tới các trang bộ nhớ trên đĩa là tương đối khó khăn. Hạn chế này sẽ được khắc phục nếu sử dụng cấu trúc cây có node fan-out lớn hơn như B-tree hay R-tree.
Space-filling curves a b c d x y z t x y z t
Hình3.15. Truy vấn điểm trên cây tứ phân
P a R R [5, oid] [6, oid] [7, oid] .
Space-filling curve định nghĩa toàn bộ thứ tự trên các ô của lưới 2D được
sử dụng cho trường hợp lưới xấp xỉ. Có hai Space-filling curve phổ biến đó là z-
order và hilbert curve. Xét lưới N × N ô, ở đó N = 2d, lưới có thể xem như cây
quadtree có độ sâu là d.
Với z-order hay z-ordering được thành lập như sau: Nhãn liên hệ với mỗi nút của cây quadtree là các một trong các con số 0, 1, 2, 3. Nút gốc có nhãn là rỗng, con NW (hoặc NE, SW, SE) của nút có nhãn k có nhãn k.0 (hay k.1, k.2, k.3). Minh họa Hình 3.16, có thể sắp xếp các ô theo nhãn. Ví dụ, chọn d = 3 và thứ tự tăng dần, ô 212 trước ô 300 và sau ô 21.
Hình 3.16. z-ordering
Hilbert curver cũng là đường cong một chiều nó gặp mọi ô trong lưới 2D,
tuy nhiên hình ảnh này không còn là z mà là (Hình 3.17)
Hình 3.17. Cấu trúc hình học của Hilbert curver
2 3
3.4.1.4 Cấu trúc hướng dữ liệu: R-tree
Các phương thức truy cập không gian sử dụng họ R-tree là các phương thức truy cập hướng dữ liệu. Các R-tree dựa vào cấu trúc phân cấp cân bằng, tại các nút của cây (là cây con hoặc lá) được ánh xạ đến một trang bộ nhớ. Tuy nhiên, nếu B-tree được xây dựng trên các khoá có giá trị đơn và dựa vào trật tự tổng thể của các khoá này thì R-tree tổ chức dữ liệu theo một quan hệ bao gồm. Để đơn giản, chỉ xét các đối tượng dữ liệu hình học thông qua hình chữ nhật nhỏ nhất bao nó (mbr).
R-tree
Mỗi nút của cây tương ứng với một trang bộ nhớ. Một nút lá chứa các mục dữ liệu, mỗi mục được biểu diễn bằng một cặp (mbr, oid). Cấu trúc này thoả mãn các tính chất tính sau:
Trừ nút gốc, tất cả các nút của cây có số con hoặc số mục dữ liệu nằm trong khoảng [m, M] với m [0, M/2].
Với mỗi mục (dr, nodeid) trong một nút N không phải nút lá, dr là hình
chữ nhật bao nút N và địa chỉ trang nhớ của nó là nodeid.
Với mỗi mục dữ liệu (mbr, oid) trong nút lá, mbr là hình chữ nhật bao đối tượng tương ứng và địa chỉ trang nhớ của đối tượng đó là oid.
Các tính chất trên của R-tree cho phép việc thực hiện các thao tác chèn, xoá một cách linh hoạt.
Với mỗi cặp (M, m) một R-tree có độ sâu d có ít nhất md+1 đối tượng và nhiều nhất Md+1 đối tượng. Ngược lại, độ sâu của một cây có N đối tượng nằm
trong khoảng [logM(N) - 1, logm(N) - 1].
Có thể minh hoạ qua ví dụ sau: Nếu kích thước trang nhớ là 4K, kích thước mỗi mục dữ liệu cần lưu là 20 byte (16 byte cho mbr, 4 byte cho oid), m
được đặt bằng 40% dung lượng trang bộ nhớ, do đó, nếu M = 204 thì m = 81. R- tree có độ sâu bằng 1 có thể lập chỉ số cho ít nhất 6561 (812) đối tượng, cây với độ sâu bằng 2 có thể có số đối tượng ít nhất là 531441 và nhiều nhất đến 8489664 đối tượng. Vì vậy, với một tập hợp gồm 1 triệu đối tượng, chỉ cần 3 lần truy cập trang bộ nhớ để duyệt cây và một phép truy cập phụ dr xác định bản ghi chứa đối tượng.
[11,12,13] d [1,2,5,6] [3,4,7,10] [8,9,14] Hình 3.17 R-tree với m = 2, M = 4 R R a b c 1 2 5 6 a 3 7 4 10 14 8 9 11 13 12 d b c
Một điểm khác biệt so với các SAM phân chia theo không gian như xét ở trên, mỗi phần tử trong cấu trúc này chỉ xuất hiện duy nhất một lần trong một nút nào đó.
R*tree
R*tree là một biến thể của R-tree với một số cải tiến nhằm làm tăng hiệu quả thuật toán chèn. Sự cải tiến tập trung ở việc tối ưu các tham số:
Sự chồng nhau của các nút, Diện tích bao phủ bởi một nút,
Chu vi của hình chữ nhật bao một nút.
Nhằm tối ưu hoá các tham số trên, không có một thuật toán thực sự hiệu nào mà phải dựa vào việc thử nghiệm các thuật toán heuristic.
Để cải tiến thuật toán phân chia. Khi một nút với dung lượng nhớ M bị
tràn, cần bổ sung một trang bộ nhớ mới, và M + 1 đối tượng này được phân chia thành 2 nút. Do kích thước không gian nghiệm là hàm mũ theo M nên không thể duyệt toàn bộ các khả năng để có được đáp án tốt nhất. Trong R-tree, thuật toán chia ban đầu tạo ra hai nhóm đối tượng cách xa nhau, tiếp đó, gán từng đối tượng trong số còn lại vào một trong hai nhóm.
Thuật toán cải tiến trong R*tree phân chia dọc theo một trục toạ độ (giả sử trục x), sau đó duyệt tất cả các khả năng phân bố của các đối tượng phía trên và dưới đường phân chia. Ưu điểm của phương pháp này được minh hoạ trong hình 3.18 (giả sử M = 4, m = 2). Với R-tree, hai đối tượng cách xa nhau A và B (hình a) được chọn làm nhân cho hai nhóm G1 và G2 tương ứng. Vì A lớn hơn khá nhiều nên các phép chèn tiếp theo phải có xu hướng đưa vào nhóm G1 (chứa A).
Nhưng trên hình b cho thấy nhóm G1 có 3 đối tượng và nhóm G2 cũng có 3 đối tượng. Đây rõ ràng là một sự phân chia không tối ưu. Ngược lại, nếu sử dụng R*tree, một đường song song với trục x được chọn nhằm tìm ra một phân hoạch không có sự chồng nhau. Để có được đường phân chia tốt nhất, cần sắp xếp các đối tượng theo một chiều nào đó. Quá trình này cần 2(2(M-2m+2)) phép tính toán. Đáp án tối ưu sẽ cho kết quả là tổng chu vi của hình bao hai nhóm là nhỏ nhất.
R*treeChooseAxis (E: tập đối tượng đầu vào)
begin min-perimeter= giá trị lớn nhất có thể for eachtrục a do sắp xếpE tương ứng với a S = 0 II Xét tất cả các khả năng phân bố fork = 1 to (M - 2m - 2) do G1 = E[1.m+k-1]; G2 = E[m+k.M+1]
// m + k -1 phần tử đầu được sắp xếp trong G1
// số còn lại được sắp trong G2.
Mg = perimeter (mbb(G1)) + perimeter (mbb(G2))
// Tính tổng các perimeter cho trục hiện tại
S = S + Mg A
B
(a) (b) (c)
Hình 3.18 Các chiến lược chia: (a) nút tràn, (b) một phần R-tree, (c) một phần R*tree
end for
//Nếu Slà giá trị nhỏ nhất cho đến thời điểm hiện tại, // Thì a là trục tốt nhất if (S <min-perimeter) then best-axis = a min-perimeter= S end if end for returnbest-axis end
Cải tiến quan trọng thứ hai của thuật toán chèn trong R*tree là chiến lược chèn lại khi xảy ra hiện tượng tràn tại một nút nào đó. Trong R-tree, khi thêm một mục dữ liệu vào một nút, nếu nút đó đã đầy thì thuật toán chèn chỉ tổ chức lại các nút có bao chồng với bao của nút ấy. Vì chỉ xét một cách cục bộ nên thông thường khó tránh việc phân trang mới. Trong khi đó, R*tree tạm thời xoá mục dữ liệu có bao lớn nhất khỏi nút bị tràn và duyệt lại, bắt đầu từ gốc để xác