Les requêtes SQL volumineuses consumnt beaucoup de mémoire

J’utilise Yii 1.1.14 avec php 5.3 sur centos 6 et j’utilise CDbCommand pour récupérer des données à partir d’une très grande table, le jeu de résultats est ~ 90 000 enregistrements sur 10 colonnes. Je l’exporte dans un fichier csv et la taille du fichier est environ 15 Mo, le script a toujours planté sans aucun message d’erreur et seulement après quelques recherches, j’ai compris que je devais augmenter le memory_limit dans php.ini pour pouvoir exécuter le script avec succès. Le seul problème est que pour une exécution réussie, j’ai dû augmenter la limite de mémoire à 512 Mo (!) Ce qui est beaucoup! et si 10 utilisateurs exécutent le même script, mon serveur ne répondra pas très bien …

Je me demandais si quelqu’un pouvait connaître un moyen de réduire la consommation de mémoire sur les requêtes SQL avec Yii? Je sais que je peux diviser la requête en plusieurs requêtes en utilisant des limites et des décalages, mais il ne semble pas logique qu’une requête de 15 Mo consum 512 Mo.

Voici le 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); 

Toutes les idées seraient grandement appréciées!

Merci,

Au lieu d’utiliser readAll qui renvoie toutes les lignes d’un seul tableau (le véritable problème de mémoire est ici), vous devez simplement utiliser une boucle foreach (consultez CDbDataReader ), par exemple:

 $command = $connection->createCommand('SELECT * FROM TEST_DATA'); $rows = $command->query(); foreach ($rows as $row) { } 

EDIT : Utilisation de LIMIT

 $count = Yii::app()->db->createCommand('SELECT COUNT(*) FROM TEST_DATA')->queryScalar(); $maxRows = 1000: $maxPages = ceil($count / $maxRows); for ($i=0;$i<$maxPages;$i++) { $offset = $i * $maxRows; $rows = $connection->createCommand("SELECT * FROM TEST_DATA LIMIT $offset,$maxRows")->query(); foreach ($rows as $row) { // Here your code } }