2010-08-06 26 views
6

Trong PostgreSQL Tôi có một truy vấn như sau đó sẽ xóa 250k hàng từ một bảng hàng 1m:Xóa nhiều hàng mà không cần khóa chúng

DELETE FROM table WHERE key = 'needle'; 

Các truy vấn mất hơn một giờ để thực hiện và trong thời gian đó, hàng bị ảnh hưởng bị khóa để viết. Điều đó không tốt bởi vì nó có nghĩa là nhiều truy vấn cập nhật phải chờ truy vấn xóa lớn để hoàn thành (và sau đó chúng sẽ thất bại vì các hàng biến mất từ ​​dưới chúng nhưng điều đó là ok). Tôi cần một cách để phân đoạn truy vấn lớn này thành nhiều phần để chúng có thể gây nhiễu ít nhất với các truy vấn cập nhật nhất có thể. Ví dụ: nếu truy vấn xóa có thể được chia thành từng phần với 1000 hàng trong chúng thì các truy vấn cập nhật khác sẽ phải chờ truy vấn xóa liên quan đến 1000 hàng.

DELETE FROM table WHERE key = 'needle' LIMIT 10000; 

Truy vấn đó sẽ hoạt động tốt, nhưng cũng không tồn tại ở bưu điện.

Trả lời

19

Hãy thử một subselect và sử dụng một điều kiện duy nhất:

DELETE FROM 
    table 
WHERE 
    id IN (SELECT id FROM table WHERE key = 'needle' LIMIT 10000); 
+0

Hoàn hảo! (Tôi không thể tin là mình không tự nghĩ về điều này) –

0

Frak's answer là tốt, nhưng điều này có thể nhanh hơn, nhưng đòi hỏi 8.4 vì hỗ trợ chức năng cửa sổ (giả):

result = query('select 
    id from (
     select id, row_number(*) over (order by id) as row_number 
     from mytable where key=? 
    ) as _ 
    where row_number%8192=0 order by id', 'needle'); 
// result contains ids of every 8192nd row which key='needle' 
last_id = 0; 
result.append(MAX_INT); // guard 
for (row in result) { 
    query('delete from mytable 
     where id<=? and id>? and key=?', row.id, last_id, 'needle'); 
    // last_id is used to hint query planner, 
    // that there will be no rows with smaller id 
    // so it is less likely to use full table scan 
    last_id = row.id; 
} 

này là tối ưu hóa sớm — điều ác . Cẩn thận.

Các vấn đề liên quan