Có một đơn đặt hàng đảm bảo IOT trong một lựa chọn?


7

Chúng ta cần thêm một prioritycột vào bảng bị tấn công khoảng 250 lần một giây, khoảng 170 lượt chọn, 125 lần chèn và 60 cập nhật. Cột sẽ là một đơn giản number(1).

Điều prioritynày không quan trọng đối với các phần chèn hoặc cập nhật, tức là không phải là một phần của khóa chính, mà tôi sẽ thi hành riêng.

Về cơ bản, chúng tôi không muốn thực hiện order byquét trên phạm vi 170 lần một giây, vì số lượng được thực hiện sẽ giảm ồ ạt.

Liệu một chỉ số bảng được tổ chức đảm bảo rằng priority = 1sẽ luôn luôn đến trước priority = 9khi chạy truy vấn sau đây:

select *
  from my_table
 where rownum < 2

Đối với ngữ cảnh nhiều hơn một truy vấn điển hình sẽ là:

select *
  from my_table
 where mod(to_number(to_char(tstamp,'ss')),1) = 0
   and done is null
   and country = 'gbr'
   and rownum < 2

Ràng buộc pk, đối với IOT, sẽ trở thành priority, rest of the pkmột ràng buộc riêng đối với pk chỉ dành cho cấu trúc. donelà null trong khoảng 99% của bảng vì vậy dù sao điều này không được chọn nhiều lắm.

Chỉ số chính được sử dụng là, tôi nghĩ rằng, country, done, to_number(to_char(tstamp,'ss')chúng tôi đã thử nghiệm khoảng 20 kết hợp và điều này đã dẫn đầu trong một chặng đường dài.

Tôi hoàn toàn không muốn thêm bất cứ lúc nào vào các truy vấn này, 0,01sa ngày được thêm bởi select là 41 phút mỗi ngày. Chúng tôi muốn giải quyết "đủ tốt" hơn là hoàn hảo.


2
Khi bạn thêm một ORDER BY priority(như trong ví dụ của Jack), bạn có thấy các SELECTtruy vấn của mình chạy chậm hơn nhiều không? Những chỉ số nào bạn có trên bàn?
Nick Chammas

bạn đang đề xuất thêm priorityvào IOT như một cột hàng đầu?
Jack nói hãy thử topanswers.xyz

@NickChammas, quá trình này đủ chậm rồi nên tôi không muốn thêm thời gian (CPU) nữa; "Đủ tốt" là đủ tốt.
Ben

@JackDoumund, vâng, chắc chắn.
Ben

4
@Ben - việc thêm thứ tự theo mệnh đề có thực sự tăng cường các kế hoạch truy vấn của bạn hay vấn đề hiệu suất là vấn đề giả định?
Mối quan tâmOfTunbridgeWells

Câu trả lời:


13

Không.

Các Điều duy nhấtđảm bảo cho kết quả thiết lập trật tự là một ORDER BYđiều khoản trong truy vấn của bạn.

Đây là một câu hỏi phổ biến về SQL, vì vậy, đáng để nhắc lại những gì tôi đã viết để trả lời các câu hỏi tương tự về SQL ServerMySQL :

Trong thế giới SQL, thứ tự không phải là một thuộc tính vốn có của một tập hợp dữ liệu. Do đó, bạn không nhận được sự đảm bảo nào từ RDBMS rằng dữ liệu của bạn sẽ quay trở lại theo một thứ tự nhất định - hoặc thậm chí theo một thứ tự nhất quán - trừ khi bạn truy vấn dữ liệu của mình bằng mệnh đề ORDER BY.

Trong Oracle, Bảng tổ chức chỉ mục (IOT) sẽ giảm thiểu khối lượng công việc mà cơ sở dữ liệu phải làm để giúp bạn sắp xếp dữ liệu theo thứ tự sắp xếp của chỉ mục. Mặc dù bạn có thể thấy rằng Oracle có xu hướng trả về các hàng được chọn từ một IOT theo cùng thứ tự đó, nhưng bạn chỉ được đảm bảo thứ tự đó khi bạn truy vấn IOT bằng một ORDER BYmệnh đề.


Tôi cũng nghĩ vậy, nhưng đã hy vọng là không :-(. Cảm ơn.
Ben

2
Tôi đoán song song sẽ phá hủy trật tự nếu bạn không yêu cầu nó.
usr

1
Cũng ORDER SIBLINGS BYcó thể cung cấp một sự đảm bảo về thứ tự kết quả trong một truy vấn phân cấp.
Benoit

1
Tôi không thể củng cố ý kiến ​​của Nick nhiều hơn. Các nhà phát triển giả định đặt hàng ngầm có thể là nguồn gốc của một số lỗi khá khủng khiếp.
Phil

3
Cụ thể trong khung thời gian Oracle 9i hoặc 10g, khi Oracle thêm nhóm băm. Tất cả các loại SQL đã bị hỏng vì những gì đã từng làm SORT GROUP BY không còn nữa.
Adam Musch

5

Có một đơn đặt hàng đảm bảo IOT trong một lựa chọn?

Không, đặt hàng không được đảm bảo mà không có ORDER BY. Không bao giờ.

Nhưng bạn có thể đạt được những gì bạn muốn như thế này:

select * from (select * from my_table order by priority) where rownum < 2;

Điều này không nhất thiết sẽ khiến Oracle phải làm nhiều việc hơn:

create table foo(priority, id, primary key (priority,id)) organization index as
select mod(level,9), level from dual connect by level<=100000;
select /*+ gather_plan_statistics */ *
from (select * from foo order by priority)
where rownum<2;
ƯU TIÊN | TÔI
-------: | -:
       0 | 9
select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
| -------------------------------------------------- ----------------------------------------------- |
| | Id | Hoạt động | Tên | Bắt đầu | Hàng điện tử | A-Hàng | Thời gian | Bộ đệm | |
| -------------------------------------------------- ----------------------------------------------- |
| | 0 | TUYÊN BỐ CHỌN | | 1 | | 1 | 00: 00: 00.01 | 2 | |
| | * 1 | QUẬN STOPKEY | | 1 | | 1 | 00: 00: 00.01 | 2 | |
| | 2 | XEM | | 1 | 1 | 1 | 00: 00: 00.01 | 2 | |
| | 3 | INDEX FULL SCAN | SYS_IOT_TOP_26495 | 1 | 100K | 1 | 00: 00: 00.01 | 2 | |
| -------------------------------------------------- ----------------------------------------------- |
| |
| Thông tin vị ngữ (được xác định bởi id hoạt động): |
| -------------------------------------------------- - |
| |
| 1 - bộ lọc (ROWNUM <2) |
| |

dbfiddle ở đây

Ý nghĩa của việc COUNT STOPKEYlà Oracle không phải trải qua tất cả các hàng củaFULL SCAN


2

Không. Cách duy nhất để đảm bảo thứ tự kết quả là thêm một ORDER BY.


2

Đối với Microsoft SQL Server, câu trả lời cũng là không và cơ chế của nó khá thú vị. Trang Sách trực tuyến về quét giải thích khái niệm quét vòng vui vẻ trong phần Quét nâng cao:

Ví dụ: giả sử rằng bạn có một bảng với 500.000 trang. UserA thực thi một câu lệnh Transact-SQL yêu cầu quét bảng. Khi quá trình quét đó đã xử lý 100.000 trang, UserB thực thi một câu lệnh Transact-SQL khác quét cùng bảng. Công cụ cơ sở dữ liệu lên lịch một bộ yêu cầu đọc cho các trang sau 100.001 và chuyển các hàng từ mỗi trang trở lại cho cả hai lần quét. Khi quá trình quét đạt đến trang thứ 200.000, UserC sẽ thực thi một câu lệnh Transact-SQL khác quét cùng bảng. Bắt đầu với trang 200.001, Công cụ cơ sở dữ liệu chuyển các hàng từ mỗi trang mà nó đọc lại cho cả ba lần quét. Sau khi đọc hàng thứ 500.000, quá trình quét cho UserA hoàn tất và quá trình quét cho UserB và UserC quấn lại và bắt đầu đọc các trang bắt đầu từ trang 1.

Có nhiều chi tiết hơn trong trang Sách trực tuyến .


Khi nào thì quét vui vẻ thực sự đi vào hoạt động? Tôi đã cố gắng để thấy điều này trước đây trên máy phát triển của tôi nhưng không thể. Nó chỉ xảy ra lúc đọc không được cam kết chẳng hạn hoặc có một số cảnh báo khác cho nó?
Martin Smith

@MartinSmith - bạn có thể đọc chi tiết đầy đủ trong trang Sách trực tuyến. Bạn cần phải ở Phiên bản doanh nghiệp (không phải Std) và nhiều truy vấn cần quét một bảng quá lớn để phù hợp với bộ nhớ.
Brent Ozar

Tôi đã thử nghiệm trên phiên bản dành cho nhà phát triển (vì vậy tôi cho rằng được tính là phiên bản Enterprise) với một bảng lớn hơn nhiều so với dung lượng RAM và vẫn không thể xảy ra điều này do đó tự hỏi liệu có một số cảnh báo khác. Tôi có thể cho nó đi tiếp sau đó nếu bạn nghĩ không có.
Martin Smith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.