2011-02-01 28 views
22

Setup:
Django 1.1.2, MySQL 5.1Làm thế nào để làm cho Django QuerySet số lượng lớn xóa() hiệu quả hơn

Vấn đề:

Blob.objects.filter(foo = foo) \ 
      .filter(status = Blob.PLEASE_DELETE) \ 
      .delete() 

đoạn này kết quả trong ORM đầu tiên tạo ra một truy vấn SELECT * from xxx_blob where ..., sau đó thực hiện một DELETE from xxx_blob where id in (BLAH); trong đó BLAH là một danh sách rất dài của id. Vì tôi đang xóa một lượng lớn các đốm màu, điều này khiến cả tôi lẫn DB đều không vui.

Có lý do nào cho điều này không? Tôi không thấy lý do tại sao ORM không thể chuyển đổi đoạn mã trên thành một truy vấn DELETE đơn lẻ. Có cách nào để tối ưu hóa điều này mà không cần đến SQL thô?

Trả lời

13

Không cần phải viết SQL hoặc người quản lý tùy chỉnh của riêng bạn hay gì đó; họ rõ ràng đang làm việc trên nó.

http://code.djangoproject.com/ticket/9519

+0

Điều này thực sự không may. Cảm ơn đã chỉ cho tôi vé. – svintus

+1

Vé cho lý do bạn đang tìm kiếm. Nó không hoàn toàn không có công đức. –

3

Bulk delete đã là một phần của django

+4

Queryset.delete() hoạt động như cách mô tả OP. –

+1

Nó vẫn không hiệu quả và kết quả trong 'OperationalError: (2006, 'MySQL server đã biến mất')' – Andrei

+0

Bulk - trong ngữ cảnh này - có nghĩa là một truy vấn SQL trọng lượng nhẹ được thực thi trên máy chủ dựa trên điều kiện WHERE. "Xóa()' của Django ORM không hoạt động như thế này. –

9

Đối với những người vẫn đang tìm kiếm một cách hiệu quả để rời xóa trong django, đây là một giải pháp khả thi:

Lý do xóa() có thể được như vậy chậm là gấp đôi: 1) django có để đảm bảo cascade xóa chức năng đúng cách, do đó tìm kiếm các tài liệu tham khảo khóa nước ngoài cho các mô hình của bạn; 2) django phải xử lý tín hiệu trước và sau khi lưu cho các mô hình của bạn.

Nếu bạn biết mô hình của bạn không có cascade xóa hoặc tín hiệu được xử lý, bạn có thể đẩy nhanh quá trình này bằng cách phải dùng đến các _raw_delete API tin như sau:

queryset._raw_delete(queryset.db) 

Xem thêm chi tiết tại here. Xin lưu ý rằng django đã cố gắng xử lý tốt các sự kiện này, mặc dù sử dụng xóa thô, trong nhiều trường hợp, hiệu quả hơn nhiều.

+0

Django có thể thực hiện điều này như một hàm công khai từ queryset là 'bulk_delete', phải không? Tại sao nó không được thực hiện? Bất kỳ lý do cấp cao nào? Và những người sử dụng 'bulk_create' nhận thức rõ tín hiệu sẽ không hoạt động. Có thể chỉ để xóa tầng? – Babu

+0

Điều này phù hợp với tôi. Chính caveat như đã đề cập là mô hình phụ thuộc ("cascade xóa") - miễn là nó là một loại đầu bảng không có phụ thuộc, điều này hoạt động, và hoạt động thực sự nhanh chóng. – nickang

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