Tôi phải cập nhật các thực thể Doctrine của mình để khớp các bản ghi bên trong tệp XML (potentionaly rất lớn). Tôi cũng phải cập nhật các liên kết ManyToMany theo dữ liệu trong XML. Đây là những gì tôi làm trong vòng lặp:doctrine2 - Làm cách nào để cải thiện hiệu quả tuôn ra?
- lấy dữ liệu từ XML
- get thực thể từ DB (nếu không tồn tại tạo mới)
- đặt thuộc tính thực thể mới
- được hiệp hội thực hiện (getter trả
ArrayCollection
đối tượng) - rõ ràng tất cả các hiệp hội (bằng cách gọi
ArrayCollection::clear()
) - thiết lập các hiệp hội mới (bằng cách gọi
ArrayCollection::add()
trong sub-loop) - tồn tại thực thể bằng cách EntityManager
Sau vòng lặp tôi gọi EntityManager::flush()
.
Vấn đề là việc xả sẽ tạo ra lượng truy vấn lớn thay vì cập nhật/chèn/xóa nhiều hàng cùng một lúc. Đối với mỗi đơn vị được thực hiện truy vấn sau đây:
- SELECT để có được tổ chức từ DB
- UPDATE để cập nhật các thuộc tính thực thể (điều này là thực sự bỏ qua bây giờ như không có tính chất thay đổi ... chưa)
- DELETE để xóa trước hiệp hội
- INSERT để chèn các hiệp hội mới
vì vậy, trong tổng số 305 cho các bản ghi trong XML tôi nhận được 915 câu hỏi (tôi đoán nó có thể đi lên đến 1220 truy vấn nếu tất cả các đối tượng sẽ thay đổi) mà làm cho thứ e nhập khẩu rất chậm.
Tôi có thể tận dụng lợi thế của IdentityMap và tìm nạp trước các thực thể trước khi lặp, nhưng vẫn có các truy vấn UPDATE/DELETE/INSERT.
- Có cách nào để cho phương pháp tuôn ra tối ưu hóa tốt hơn các truy vấn (sử dụng nhiều chèn, WHERE IN thay vì nhiều truy vấn DELETE, v.v ...) không?
- Đây có phải là hành vi bình thường của phương pháp xả hoặc tôi đang làm điều gì sai?
- Có thể có vấn đề trong cách tôi cập nhật các liên kết của pháp nhân. Có cách nào tốt hơn làm thế nào để làm điều này? (thay vì "get/clear/add" method)
- Tôi biết rằng Doctrine không dành cho xử lý betch khối lượng, nhưng tôi nghĩ rằng việc sử dụng nó cho nhập XML là cách tốt nhất để tránh sự không nhất quán của DB có thể xuất hiện với một cách tiếp cận không phải ORM. Có đúng không?
- Nếu cách tiếp cận trên sai, tôi nên giải quyết vấn đề như thế nào?
+1 cho tôi biết rằng tôi không điên :) –
Theo nghiên cứu của tôi không có cách nào để tối ưu hóa tốt hơn việc nhập khi vẫn sử dụng ORM. Tôi đã thêm một số thông tin vào câu trả lời cho các googlers tiềm năng trong tương lai. –
Sau khi thêm $ em-> clear(), sự kiên trì hoạt động nhanh hơn rất nhiều, hoàn toàn giải quyết được vấn đề của tôi. Nếu bạn muốn chèn nhanh hơn, hãy vô hiệu hóa chỉ mục xây dựng lại sau mỗi truy vấn chèn. $ conn-> preparation ('SET autocommit = 0;') -> execute(), và sau khi truy vấn, làm $ conn-> preparation ('COMMIT;') -> execute(); – tomazahlin