EllisLab text mark
Advanced Search
1 of 2
1
   
Active Record large result memory exhausted
Posted: 09 May 2012 04:44 PM   [ Ignore ]
Avatar
Joined: 2010-05-20
24 posts

Hi there I’m trying to do a simple operation over a table with 600.000 records
and i’m getting (from x-debug):

Fatal errorAllowed memory size of 134217728 bytes exhausted (tried to allocate 72 bytesin ...../system/database/drivers/mysql/mysql_result.php

5 1.0201 4548320 CI_DB_result
->next_row( ) ../crefis.php:26
6 1.0202 4548456 CI_DB_result
->result( ) ../DB_result.php:347
7 1.0202 4548456 CI_DB_result
->result_object( ) ../DB_result.php:51
8 3.0983 134170688 CI_DB_mysql_result
->_fetch_object( ) ../DB_result.php:119
9 3.0983 134170768 mysql_fetch_object 
( ) ../mysql_result.php:167 

the ->get() method gets executed well but the problem is faced when i try to walk thru the results

while($row$query->next_row())

or

foreach ($query->result() as $row

Is ActiveRecord class (or the mysql driver of CI) intended only for small tables and resulsets?
It seems that 128M is more than enough.
I ran this same process over plain php and ADODB and it works perfect.
Any help would be highly appreciated.

 
Posted: 09 May 2012 05:45 PM   [ Ignore ]   [ # 1 ]   [ Rating: 0 ]
Avatar
Joined: 2009-02-19
3819 posts

I imagine it has to do with however you are processing your data.  You should post more code where you get the data from the db and then manipulate it, especially more of the loops you started to post above.

 Signature 
 
Posted: 09 May 2012 07:04 PM   [ Ignore ]   [ # 2 ]   [ Rating: 0 ]
Avatar
Joined: 2010-05-20
24 posts

Hey CroNiX thanks for the fast reply,
The code that I didn’t post is irrelevant is a simple ->get() from a table.
The error raises with the code above, that is because of this code at DB_result.php

@line 118

$this->_data_seek(0);
  while (
$row $this->_fetch_object())
  
{
   $this
->result_object[] $row;
  
}

  
return $this->result_object

OMG! all the data is added to the object! this way is impossible to work with large resulsets.
is there a way to tell the class not to load all the results?

Thanks in advance!
Juan

 

 
Posted: 09 May 2012 07:11 PM   [ Ignore ]   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2009-02-19
3819 posts

$query->free_result()

 Signature 
 
Posted: 09 May 2012 09:51 PM   [ Ignore ]   [ # 4 ]   [ Rating: 0 ]
Avatar
Joined: 2010-05-20
24 posts

sorry it didn’t work:

$query $this->db->get('mytable');

//---mytable has 1 Million records

$query->free_result();

foreach (
$query->result() as $row)
{
    
echo $row->id;

you may think I’m a noob (and you’re right) but what’s the point of this:

$query $this->db->get('mytable');



foreach (
$query->result() as $row)
{
    
echo $row->id;
}
$query
->free_result(); 

if the memory get exhausted on the $query->result() statement.

I dont want to free the results I didn’t used! I want to be able to use them first then I will set them free.
What do you think?

 

 
Posted: 09 May 2012 10:21 PM   [ Ignore ]   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2009-06-19
6267 posts

Try:

ini_set"memory_limit","256M"); 

Or in your .htaccess file try this and see if it helps, otherwise you will need to edit the MySQL config file.

.htacces

php_value memory_limit 256M 

You can also edit your php.ini file and make the change in it!

 

 Signature 

Ceritfied State of CT Computer Programming Teacher.
Custom Designed Icons, eBook Covers Software Boxes. CD, DVD Etc. New iPhone® Tab Bar Icons and iPhone® Applications Icons.

STOP! Before posting your questions, remember the WWW Golden rule:
What did you try? What did you get? What did you expect to get?

Input -> Controller | Processing -> Model | Output -> View

 
Posted: 10 May 2012 09:48 AM   [ Ignore ]   [ # 6 ]   [ Rating: 0 ]
Avatar
Joined: 2010-05-20
24 posts

@InsiteFX why add more memory?  8mb should be more than enough for iterate a record set, and i have 128MB (16x more)

I think I’m hitting a design error here.
The big questions is:

Why the CodeIgniter abstraction layer is trying to add ALL the rows to the object instead of providing a pointer to the results?

imho: a result of a query should not give me all the results into the object(which lives in the memory) but instead, provide a way to navigate through the results.

in fact this is the first time I see this kind of defect in a db abstraction class (i used to use ADODB,mongo,etc..)

 
Posted: 10 May 2012 09:59 AM   [ Ignore ]   [ # 7 ]   [ Rating: 0 ]
Avatar
Joined: 2009-06-19
6267 posts

I did not say to add more memory! What I said was to raise the php script memory.

 Signature 

Ceritfied State of CT Computer Programming Teacher.
Custom Designed Icons, eBook Covers Software Boxes. CD, DVD Etc. New iPhone® Tab Bar Icons and iPhone® Applications Icons.

STOP! Before posting your questions, remember the WWW Golden rule:
What did you try? What did you get? What did you expect to get?

Input -> Controller | Processing -> Model | Output -> View

 
Posted: 10 May 2012 02:42 PM   [ Ignore ]   [ # 8 ]   [ Rating: 0 ]
Avatar
Joined: 2010-05-20
24 posts

@InsiteFX, I see what’s your point, do you see mine?

may be i didn’t have myself clear enough.
if so I will aprovide a generic example from where this defect can be tested.
yes anyone can get this error even raising the amount of memory for a single script, sooner or later the ammount of rows will beat your ram memory, that’s why resulsets are not stored in memory unless you ask for or you are in a caching strategy where memcaching is needed.

 
Posted: 10 May 2012 03:24 PM   [ Ignore ]   [ # 9 ]   [ Rating: 0 ]
Avatar
Joined: 2009-06-19
6267 posts

I see your point also, but what I think your going to end up doing is using

limit and offset to retrive only a certain amount of records at a time.

I can not see anyone having to load a million records at one time.

If you are displaying them then you would need to use the CI Pagination Class.

 Signature 

Ceritfied State of CT Computer Programming Teacher.
Custom Designed Icons, eBook Covers Software Boxes. CD, DVD Etc. New iPhone® Tab Bar Icons and iPhone® Applications Icons.

STOP! Before posting your questions, remember the WWW Golden rule:
What did you try? What did you get? What did you expect to get?

Input -> Controller | Processing -> Model | Output -> View

 
Posted: 10 May 2012 09:36 PM   [ Ignore ]   [ # 10 ]   [ Rating: 0 ]
Avatar
Joined: 2010-05-20
24 posts

that’s why programming it’s such an exciting job, one day you’re working with a shopping cart and the other you end up trying to run a process over a million records.!!!


My problem right now is that I’m trying to do it with CI
I know at least 3 other ways to do the same without using CI, but I made this post hoping for an answer of why can’t I open a table with a million records?
In fact I can hack the library to do what I want.

 
Posted: 11 May 2012 03:29 AM   [ Ignore ]   [ # 11 ]   [ Rating: 0 ]
Avatar
Joined: 2008-10-20
397 posts

I’ve had similar issues but it always boiled down to a crap SQL query, after running the query try a print $this->db->last_query(); and running it in phpmyadmin (Unless it’s really really simple).

 Signature 

Mat-Moo
Image moo - the easy to use image library!
MatMoo.com!
E-Mail Remind - Free reminders by email
Printfetti - Your photos on confetti!

 
Posted: 11 May 2012 03:30 AM   [ Ignore ]   [ # 12 ]   [ Rating: 0 ]
Joined: 2007-11-23
332 posts

As InsiteFX has said. Why “WOULD” you want to open a table with a million records?

Any developer worth their salt should know that large tables must be paged/paginated into chunks.

I’ve only ever come across two instances where you would “need” to process large amounts of data, in one go and in those instances, I have used a direct connection to the database using PHP, i.e. mysql_open.

CodeIgniter and ActiveRecord (IMO) has been built for the common developer who, every day, has to constantly keep on writing the same code over and over again. It’s been build so that accessing single, or small result sets is made extremely easy, where normally, it would require a lot more work.

If you need to process large result sets, I would suggest using plain PHP and MySQL calls, so that CI and ActiveRecord do not consume any additional memory during the processing…

 
Posted: 11 May 2012 08:32 AM   [ Ignore ]   [ # 13 ]   [ Rating: 0 ]
Avatar
Joined: 2010-05-20
24 posts

Hey thanks for the replies.

The query is very simple, jsut a select from a table.
The explanation of my needs are irrelevant to the bug/defect, you can’t criticize my needs based on your own.
May be it’s not the most common scenario but an abstraction layer should be capable of handle 1M records seamlessly like most other abstraction layers.

If DB layer of CI is intended for small resulsets, that should be noted and remarked in the docs, and the library should be safe in that way and handle the exceptions.

Let’s say you start with an empty database and for some reason you end up with a big result, then you will end up with a memory exhaustion error.

 
Posted: 11 May 2012 08:39 AM   [ Ignore ]   [ # 14 ]   [ Rating: 0 ]
Joined: 2007-11-23
332 posts

If you can provide an actual reason for returning 1M records in one resultset, then maybe there is a flaw in the CI DB system, but under normal circumstances, even databases with more than 1M records will work fine on the CI DB system by use of pagination or correctly processing the data.

For example, regardless of how many records you have, you should have pagination to breakdown the results when presenting. i.e.

select from Table limit 0100 


which returns 100 rows.

If you have 1M records that you need to process in one movement, you can either use native mysql calls that PHP provides, or what’s probably better, is to batch process them in say 10000 rows at a time.

 
Posted: 11 May 2012 09:20 AM   [ Ignore ]   [ # 15 ]   [ Rating: 0 ]
Avatar
Joined: 2010-05-20
24 posts

I don’t need to present this just a process over thouse records so pagination is not needed

 
1 of 2
1