Cập nhật tất cả các hàng


12

Tôi muốn biết cách hiệu quả nhất để cập nhật mỗi hàng trong một bảng Oracle cực lớn cho một cột. Ví dụ:

update mytable set mycolumn=null;

hoặc là:

update mytable set mycolumn=42;

Kiến thức của tôi rất có thể cũ. Những gì tôi làm là thay đổi bảng để thả cột. Sau đó, tôi thay đổi bảng để thêm cột với giá trị mặc định của giá trị mới mà tôi muốn sử dụng. Sau đó, tôi thay đổi bảng để loại bỏ giá trị mặc định cho cột. Tôi thấy điều này nhanh hơn nhiều so với việc chỉ chạy một bản cập nhật, nhưng tôi có cảm giác rằng có một phương pháp tốt hơn.


Theo như tôi hiểu thì việc thêm một cột không null mới với mặc định là siêu dữ liệu chỉ thay đổi trong Oracle. Tôi nghi ngờ họ sẽ tối ưu hóa trường hợp "cập nhật tất cả các hàng thành cùng một giá trị". Đây có phải là một hoạt động phổ biến cho bạn?
Martin Smith

1
Chỉ cần thử cả hai phương pháp và thời gian chúng. Điều gì ngăn cản bạn làm điều này? Kìa thực tế bạn phải kết thúc với cùng một kết quả, không phải với một kết quả khác! Nếu không, sự so sánh là không hợp lệ.
tvCa

@tvCa Mình đã thử cả hai cách. Nếu tôi chỉ làm một bản cập nhật, nó sẽ chạy trong khoảng hai giờ và sau đó tôi sẽ giết nó. Nếu tôi thả một cột, chỉ mất vài giây. Thêm một cột không có giá trị mặc định (làm trống cột) chỉ mất vài giây. Thêm một cột với giá trị mặc định mất khoảng 30 phút. Vì vậy, nếu tôi muốn, ví dụ, đặt tất cả các giá trị trong một cột thành 'Một số giá trị', tôi hiện đang thả và thêm cột. Tôi chỉ muốn biết nếu có một cách nhanh hơn để làm điều đó.
kainaw

2
Bạn đang sử dụng 11gR2? @MartinSmith là chính xác. Xem ở đây để biết mô tả về cách thêm cột mới bằng DEFAULT vì KHÔNG NULL là một thay đổi nhanh hơn nhiều so với việc thêm nó dưới dạng NULL, điều này sẽ buộc cập nhật tất cả các hàng trong bảng (giống như đưa ra câu lệnh CẬP NHẬT). Vấn đề tôi thấy là loại bỏ giá trị DEFAULT sau đó, vì hiệu suất tăng đến từ việc lưu trữ DEFAULT trong từ điển. Bạn cũng sẽ phải đối phó với ràng buộc KHÔNG NULL tại thời điểm đó.
ansible

Câu trả lời:


2

Rất nhiều phụ thuộc vào hoạt động khác đang diễn ra đối với bảng này trong khi bạn đang thực hiện cập nhật hàng loạt này. Tôi hy vọng bạn có một số loại môi trường thử nghiệm nơi bạn có thể chạy một số mẫu về những gì bạn muốn làm và có ý tưởng về cách nào là tốt nhất. Tôi sẽ thử:

  1. Chạy đơn update table set column_name = blah;
  2. Tạo một vòng lặp plSql để chọn tất cả các khóa chính trong bảng và lặp qua chúng updating the column=blahvà cam kết mỗi bản cập nhật X (có thể là 10000). Bạn có thể song song mã này bằng cách sao chép mã và sao chép mã làm một phần riêng biệt của Khóa chính.

Chúng tôi có một vấn đề rất giống với một bảng được sử dụng rất tích cực trong hệ thống OLTP và chúng tôi có thể song song với nó 5x và chạy mà không có tác động khóa người dùng nào trên bảng hàng 100+ MM cam kết cứ sau 10000. Bạn không nói như thế nào bảng của bạn lớn hoặc loại ứng dụng nào bạn đang chạy, nhưng loại giải pháp này có thể phù hợp với bạn.


0

Để nhanh chóng UPDATE, hãy chắc chắn rằng bạn không có bất kỳ kích hoạt nào đang bắn.

SELECT trigger_name, status FROM user_triggers WHERE table_name = 'MYTABLE';

ALTER TABLE mytable DISABLE ALL TRIGGERS;

Hãy chắc chắn chỉ kích hoạt lại những cái bạn muốn khi bạn hoàn thành.

ALTER TRIGGER mytrigger ENABLE;

Bạn cũng có thể đang chạy vào chi phí bảo trì chỉ mục. Hãy thử xây dựng lại các chỉ mục của bạn một cách riêng biệt. Để làm điều đó, câu trả lời ở đây bằng pappes sẽ rất hữu ích: /programming/129046/disable-and-later-enable-all-table-indexes-in-oracle

Tôi đang lặp lại câu trả lời của pappes ở đây để tham khảo. (Lưu ý rằng lệnh SPOOL này đưa ra các giả định về nền tảng và môi trường của bạn.)

set pagesize 0    
alter session set skip_unusable_indexes = true;
spool c:\temp\disable_indexes.sql
select 'alter index ' || u.index_name || ' unusable;' from user_indexes u;
spool off
@c:\temp\disable_indexes.sql

Hãy nhập ...

select 'alter index ' || u.index_name || ' rebuild online;'
  from user_indexes u;

-1

xóa chỉ số. cập nhật cột. trả lại chỉ số nhưng nếu cột chứa một và cùng một giá trị cho tất cả các hàng, bạn có thể bỏ chỉ mục.


-2

Nếu bạn không có giới hạn về không gian, bạn có thể tạo một bảng mới, giống như bảng của bạn với cột mới được thêm vào bảng đó và xóa bảng cũ:

create new_table as
select old_table.*, (with or without default_Value) as new_column
from old_table;

1
Điều này sẽ hiệu quả hơn? Tại sao? Và nếu có các FK tham chiếu bảng hiện có thì sao?
ypercubeᵀᴹ

có, bạn có thể thử nó trên bảng mẫu khác và tự xem kết quả. Nếu có FK, tôi không biết chính xác nhưng bạn có thể vô hiệu hóa và kích hoạt chúng nếu nó hiệu quả.
E_Salamon

-3

Hãy thử nhiều chuỗi cập nhật / cam kết. Chèn / Cập nhật / Xóa quá nhiều hàng mà không có cam kết dẫn đến tải IO nặng. Nó có thể được tối ưu hóa khá rõ khi biết kích thước khối và kích thước bản ghi và công cụ.

Để xóa toàn bộ dữ liệu trên một bảng, truncate table xtốt hơn là delete from x. Ngoài ra thanh trừng làm cho một khối lượng công việc quá trình khác.

Chỉnh sửa: Bạn có thể sử dụng inmemorytùy chọn, tải bảng trong bộ nhớ ở định dạng cột và sau đó thực hiện cập nhật. nó thực sự phụ thuộc vào các mối quan hệ và cấu trúc DB của bạn. Xem bài viết này .


3
Họ muốn cập nhật một cột của bảng. Tôi không thấy làm thế nào truncatehoặc deletesẽ được giúp đỡ.
ypercubeᵀᴹ

@ypercube Tôi chỉ giải thích cách thao tác nhiều dữ liệu mà không cam kết dẫn đến tải IO không mong muốn; hoặc là cập nhật hoặc OLTP khác.
Xảo quyệt

3
Bạn có thể giải thích mức độ thường xuyên làm giảm I / O không? Họ sẽ không tăng I / O vì các trạm kiểm soát chứ?
mustaccio

3
Việc bạn sử dụng thuật ngữ không theo quy tắc ("tạp chí tx", "tuôn ra phiên của bạn") hơi khó hiểu. Cho dù bạn sử dụng nhiều giao dịch ngắn hay một giao dịch lớn, tổng khối lượng hồ sơ làm lại được tạo sẽ giống nhau. Các thao tác I / O chỉ xảy ra khi bộ đệm nhật ký làm lại được ghi vào đĩa (để lại các điểm kiểm tra bộ đệm bộ đệm một mình), xảy ra khi cam kết hoặc khi bộ đệm làm lại gần đầy. Sau đó, nếu bạn cam kết thường xuyên, bạn sẽ tạo thêm I / O, vì vậy tôi tự hỏi làm thế nào điều đó có thể làm giảm I / O.
mustaccio

4
Bạn có thể muốn đọc những gì Tom Kyte đã nói về "cam kết thường xuyên": asktom.oracle.com/pls/apex/... " là sai, sai, sai Vì vậy, sai .... Vì vậy, rất rất sai. "
a_horse_with_no_name
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.