2011-09-28 40 views
8

Tôi đang làm việc trên một dự án mà tôi phải thu thập rất nhiều dữ liệu từ cơ sở dữ liệu. Tôi đang sử dụng Symfony2 (symfony bf1281aebdc842a39ec0eb7438e1ea3fca9b9705) và Doctrine2 (doctrine 3b3186ee98392802a44118cd421a3530119aa7eaand) làm cơ sở làm việc.Làm thế nào để xử lý các tập hợp giáo lý lớn và các hiệp hội

Vấn đề tôi gặp phải là tôi phải tìm khoảng 15.000 bài viết. Sau đó, tôi cần phải lặp qua tất cả chúng để tìm nạp thêm dữ liệu trên cơ sở id bài viết (có các liên kết trực tiếp và gián tiếp với phương tiện hoặc giá được thừa kế, v.v.). It's ok cho khoảng 50-100 hồ sơ, nhưng nếu tôi muốn sử dụng nhiều hồ sơ phải mất rất nhiều ram một thời gian để lấy tất cả mọi thứ từ cơ sở dữ liệu.

Có cách nào để lặp qua dữ liệu mà không cần sử dụng hết tất cả ram còn lại không? Có cách nào để nói giáo lý ngừng sử dụng tài liệu tham khảo?

Cảm ơn bạn trước vì đã trợ giúp!

Trả lời

3

Khó trả lời mà không có thêm chi tiết cụ thể về những gì bạn đang cố gắng làm, chính xác.

Học thuyết thường không phù hợp cho việc thu thập dữ liệu lớn như bạn có thể mô tả. Tôi có một số dự án mà trở lại trên chỉ bằng cách sử dụng DBAL để chạy SQL thô cho những thứ như báo cáo phức tạp.

Điều đó nói rằng, nếu bạn không thực sự cần tất cả các bản ghi 15k được tải cùng một lúc, thì đừng tải chúng cùng một lúc! Lấy 50, xử lý chúng, bộ nhớ miễn phí và lặp lại. Cách tiếp cận này có thể giữ tổng số khi bạn đi, vì vậy có thể nhận được một số thống kê tổng hợp cho toàn bộ tập hợp.

Điều đó nói rằng, nếu bạn cần nội dung tổng hợp, bạn có thể xây dựng một số loại "báo cáo" và bạn cũng có thể sử dụng SQL thuần túy hoặc thậm chí một số thủ tục được lưu trữ và đừng để ORM tham gia.

+0

và cho tôi biết, ở chính xác những gì Symfony hướng ứng dụng bạn có thể cần 15k hồ sơ cùng một lúc? Chỉ khai thác dữ liệu cần nhiều dữ liệu và không nên được cung cấp bởi Symfony. –

3

Bạn có thể nhìn vào sử dụng lặp đi lặp lại (step-by-step) hydrat hóa trong Học thuyết:

$em = $this->getDoctrine()->getEntityManager(); 
$q = $em->createQuery("<DQL to select the objects I want>"); 
$iterableResult = $q->iterate(); 
while (($row = $iterableResult->next()) !== false) { 
    // do stuff with the data in the row, $row[0] is always the object 
    $em->detach($row[0]); // detach from Doctrine, so that it can be GC'd immediately 
} 

chi tiết từ this article, dưới Khối lượng xử lý đối tượng

+0

FYI: liên kết bị hỏng – Tieme

1

Có thực sự là một cách khác, nhưng bạn sẽ không thích nó. Bạn có thể sử dụng mysql thuần túy :) Khi tôi cố gắng lấy các đối tượng 450k từ cơ sở dữ liệu bằng cách sử dụng getRepository ("..") -> findAll() - nó cho đến khi tôi đóng tập lệnh :). Vì vậy, tôi đã sử dụng mã như

$c = $doctrine->getConnection(); 
    mysql_connect($c->getParams()['host'],$c->getParams()['user'],$c->getParams()['password']);//$link = 
    mysql_select_db($c->getParams()['dbname']); 
    $qid = mysql_query("SELECT id FROM TABLENAME"); 
    while($i = mysql_fetch_row($qid)) { 
     $object = $doctrine->getRepository("...")->find($i[0]); 

tôi có đối tượng đầu tiên sau khi 1,7 giây, mà là hoàn toàn chấp nhận được đối với tôi. Trừ mã lộn xộn :(

Sau khi googling một chút tôi nằm bạn thắc mắc và doctrine manuall. Sau khi viết lại tôi đã nhận mã

$iterableResult = $doctrine->getManager()->createQuery("SELECT c FROM ENTITY c")->iterate(); 

    while (($row = $iterableResult->next()) !== false) { 
     $object = $row[0]; 
    } 

Mã ở trên cung cấp mục đầu tiên trong 2,4 giây, mà là cực kỳ nhanh chóng, như đối với các doctrine2 và 450K mục trong bảng

Quan điểm của tôi là -. doctrine2 đã có hầu hết mọi thứ bạn cần cho "đời thực" sử dụng, nhưng bạn vẫn có thể đơn giản hóa cuộc sống của bạn với mã xấu xí trường cũ :)

CẬP NHẬT: Đừng quên thác tất cả các thực thể được nạp.Và trong symfony2 bạn cũng cần phải vô hiệu hóa SQL đăng nhập bằng cách chạy mã

$doctrine->getConnection()->getConfiguration()->setSQLLogger(null); 
6

lưu dòng khác bằng cách sử dụng:

$iterableResult = $doctrine->getManager()->createQuery("SELECT c FROM ENTITY c")->iterate(); 

while ((list($obj) = $iterableResult->next()) !== false) { 
    // do something with $obj 
    $em->detach($obj); 
} 
0

Từ học thuyết documentation:

$batchSize = 20; 
$i = 0; 
$q = $em->createQuery('select u from MyProject\Model\User u'); 
$iterableResult = $q->iterate(); 
foreach ($iterableResult as $row) { 
    $user = $row[0]; 
    $user->increaseCredit(); 
    $user->calculateNewBonuses(); 
    if (($i % $batchSize) === 0) { 
     $em->flush(); // Executes all updates. 
     $em->clear(); // Detaches all objects from Doctrine! 
    } 
    ++$i; 
} 
$em->flush(); 
Các vấn đề liên quan