Reputation: 97
I am using Yii 1.1.14 and I am trying to retrieve a big data set (~80,000 records / 10 columns) from an oracle 11.2 database.
My problem is that the entire script just crashes after a few minutes without triggering any errors / exceptions. I also checked the php and apache logs but there is no indication for any error.
The script is executed from a browser and I only get a blank page back with no data.
Here is the code:
set_time_limit(0);
$connection = new CDbConnection($dsn,$username,$password);
$command = $connection->createCommand('SELECT * FROM TEST_DATA');
$result = $command->queryAll(); //this is where the script crashes
print_r($result);
//Please disregard any typos, I pasted only a portion of the code.
After some debugging, I realize that the script fails on the $command->queryAll() line, But When I set a limit to 60,000 records (~9MB file) the script dos not fail and I get the results printed on the page, so I know the codes works fine.
I suspect that the crash is related to memory consumption but usually it triggers an error and I have tried raising the memory_limit in php.ini to 256MB but this didn't solve it. I also tried setting error reporting to E_ALL in order to try and get any errors / exceptions raised.
I am using apache with php 5.3 on a centos 6 server.
I am all out of ideas and I would really appreciate it if anyone here could help me out.
EDIT: I found the problem, it is a memory issue, I figured out that for a ~10MB result set / 10MB file you will need to set the memory limit on php.ini to 256MB (which is a lot!), I guess I will not use Yii AR but issue a plain php command.
Upvotes: 1
Views: 394
Reputation: 915
I can hardly imagine a situation, when 60K records must be printed on the page. I suggest you not doing findAll()
but using paginated results as in CGridView
or CListView
:
$dataProvider=new CActiveDataProvider( TestData::model() );
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
));
Its very simple to rewrite your code. E.g. if you are doing (even with scopes)
TestData::model()->published()->top(5)->findAll()
just cut-off last part and you have an argument to CActiveDataProvider
contructor
new CActiveDataProvider( TestData::model()->published()->top(5) );
UPDATE
Try to query by portions:
$limit = 1000 ;
$passes = ceil( Yii::app()->db->createCommand( 'SELECT COUNT(*) FROM {{test_data}}' )->queryScalar() / $limit ) ;
for ( $pass = 0 ; $pass < $passes ; $pass++ ) {
$command = Yii::app()->db->createCommand()
->select('*')
->from( '{{test_data}}' )
->limit( $limit )
->offset( $pass * $limit ) ;
$result = $command->queryAll() ; // here is your peace of data
}
Upvotes: 1