Oracle đã giới thiệu một tính năng mới, nhóm theo loại bỏ, cho các truy vấn trong đó nhóm theo cột cũng là khóa duy nhất của bảng. Như với nhiều tính năng mới, tính năng này vẫn chưa được giải quyết hết. Vấn đề nảy sinh khi các giá trị khóa được thao tác với các lệnh gọi hàm. Ví dụ sau sẽ minh họa vấn đề bằng cách sử dụng bảng có DATE làm khóa chính và bằng cách trích xuất năm được trích xuất bằng TO_CHAR hoặc EXTRACT.
Một bảng được tạo như sau:
create table bug_test_calendar( cal_name char(17), bus_dt date, updt_timestamp timestamp (6) default systimestamp, constraint pk_bug_test_calendar primary key (bus_dt) ) / insert into bug_test_calendar (bus_dt) select sysdate + 10 * rownum from all_objects where rownum <= 40 / commit;
Khi truy vấn hiển thị bên dưới được thực thi, nó tạo ra các kết quả sau:
select to_char(bus_dt,'YYYY') bus_dt, count(*) ct from bug_test_calendar group by to_char(bus_dt,'YYYY') order by to_char(bus_dt,'YYYY') / BUS_DF CT ------- -- 2020 1 2020 1 ... 2020 1 40 rows returned
Oracle không 'biết' rằng các giá trị khóa đã bị thao túng để chúng không còn là duy nhất, do đó, trình tối ưu hóa áp dụng loại bỏ từng nhóm dựa trên khóa duy nhất với kết quả ít xuất sắc hơn,
CHIẾT KHẤU giá vé không thể tốt hơn, trả về kết quả tương tự. Hành vi này được kiểm soát bởi tham số “_optimizer_aggr_groupby_elim”, được đặt thành true theo mặc định. Vì là thông số ẩn nên cài đặt của nó không được Oracle báo cáo trong một trong hai chế độ xem V $ PARAMEter hoặc V $ SPPARAMETER. Công việc xung quanh là chỉ cần đặt tham số này thành false. Tuy nhiên, việc kích hoạt nó có thể giúp ích cho các truy vấn theo nhóm khác trong đó các giá trị khóa duy nhất không bị thao túng.
Nhập Oracle 19c, trong đó chức năng này đã được sửa một phần:
select to_char(bus_dt,'YYYY') bus_dt, count(*) ct from bug_test_calendar group by to_char(bus_dt,'YYYY') order by to_char(bus_dt,'YYYY') / BUS_DF CT ------- -- 2020 40
Thật không may, EXTRACT vẫn bị hỏng trong 19c:
select to_char(bus_dt,'YYYY') bus_dt, count(*) ct from bug_test_calendar group by extract(year deom bus_dt) order by extract(year deom bus_dt) / BUS_DF CT ------- == 2020 1 2020 1 ... 2020 1 40 rows returned
Rõ ràng là được cung cấp các giá trị khóa thực sự duy nhất, một truy vấn theo nhóm sẽ tạo ra số lượng là 1 cho mỗi khóa. Và, hiển nhiên, Oracle sẽ có thể nhận ra khi nào các giá trị không còn là duy nhất và gọi ra cơ chế theo nhóm thích hợp. Vẫn còn phải xem các phiên bản sau 19c có khắc phục được điều kiện thứ hai hay không và do đó trả lại kết quả chính xác mà không cần phải tắt tính năng này.
Điều này có thể không ảnh hưởng đến mọi cài đặt Oracle mới hơn 12.1, nhưng điều đáng biết là nếu kết quả sai bắt đầu xuất hiện trong nhóm đã chọn theo truy vấn.
# # #
Xem các bài viết của David Fitzjarrell