11
votes

L'exécution d'une déclaration prend-elle toujours une mémoire pour le jeu de résultats?

Un collègue qui exécute une instruction SQL met toujours la donnée dans la RAM / Swap par le serveur de base de données. Ainsi, il n'est pas pratique de sélectionner de gros ensembles de résultats.

Je pensais que ce code xxx

récupère la rangée de résultats de résultat à la ligne, sans qu'il soit chargé vers la RAM. Mais je ne trouve aucune référence à cela dans DBI ou MySQL Docs. Comment le jeu de résultats est-il vraiment créé et récupéré? Est-ce que cela fonctionne de la même manière pour des sélectionnes simples et des jointures?


3 commentaires

Question sur le but, pourquoi vous devez chercher des lignes d'enregistrement de millions de dollars et d'une extraction d'itérale? mysqldump devrait être plus approprié


@ajreal: Je dois traiter toutes les lignes par ordre d'insertion et générer des rapports.


Ok, est-ce rationnel de faire ça? Utilisation de la fonction MySQL pour générer une vue, la table temporaire n'est pas suffisante pour le rapport? ou même envisager de jeter les gros résultats dans le fichier et ouvrez le fichier de traitement


4 Réponses :


1
votes

Je ne suis pas très familier avec cela, mais cela me semble que dBD :: MySQL peut soit tout reproduire à l'avant, soit uniquement au besoin, en fonction de l'attribut mysql_use_result. Consultez la documentation DBD :: MySQL et MySQL.


0 commentaires

6
votes

Ce n'est pas vrai (si nous parlons du serveur de base de données lui-même, pas de couches de clients).

mysql peut tamponner l'ensemble des résultats, mais ce n'est pas nécessairement fait, et s'il est fait, pas nécessairement dans RAM . .

Les Resulatset sont tamponnés si vous utilisez des vues inline ( Sélectionnez parmi (SELECT ...) ), la requête doit trier (qui est affichée comme à l'aide de FilseTort ), Ou le plan nécessite de créer une table temporaire (qui est indiqué comme en utilisant temporaire dans le plan de requête).

Même si à l'aide de temporaire , mysql ne conserve que la table en mémoire lorsque sa taille ne dépasse pas la limite définie dans TMP_TABLE . Lorsque la table pousse sur cette limite, elle est convertie de mémoire dans myisam et stocké sur disque.

vous, cependant, peut instruire explicitement mysql pour tamponner les résultatsset en ajoutant sql_buffer_result instruction sur le plus externe SELECT . .

Voir le docs Pour plus de détails.


0 commentaires

3
votes

Non, ce n'est pas comme ça que ça marche.

La base de données ne tiendra pas des lignes en RAM / Swap.

Cependant, il va essayer et MySQL essaie de courir ici, de mettre en cache autant que possible (index, résultats, etc.). Votre configuration MySQL donne des valeurs pour les tampons de mémoire disponibles pour différents types de caches (pour différents types de moteurs de stockage) - vous ne devez pas autoriser ce cache à échanger.

Testez-le
En bout de ligne - il devrait être très facile de tester cela à l'aide du client uniquement (je ne sais pas DBI de Perl, cela pourrait, mais je doute que cela oblige MySQL à tout charger sur préparer). Quoi qu'il en soit ... Testez-le:

Si vous émettez réellement une préparation sur SELECT SQL_NO_CACHE MILLIVERS_ROWS DE TABLE puis fetchez seulement quelques lignes hors de millions de milliards. Vous devriez ensuite comparer les performances avec Sélectionnez SQL_NO_Cache uniquement_fetched_rows à partir de la table et voyez comment ce tarif. Si la performance est comparable (et rapide), je pense que vous pouvez appeler le bluff de votre collègue.

Également si vous activez le journal des instructions réellement émises à MySQL et que nous vous donnons une transcription que nous (non Perlanks) peut donner une réponse plus définitive sur ce qui serait MySQL.


0 commentaires

7
votes

Votre collègue a raison.

Par défaut, le module Perl DBD :: mysql utilise mysql_store_result, qui lit en effet dans toutes les données de sélection et le cache dans la RAM. À moins que vous ne changez que par défaut, lorsque vous recherchez la ligne par ligne dans DBI, il s'agit simplement de les lire de ce tampon de mémoire.

C'est généralement ce que vous voulez sauf si vous avez de très grands ensembles de résultats. Sinon, jusqu'à ce que vous obteniez les dernières données de MySQLD, il doit contenir que les données prêtes et que je crois comprendre est qu'elle provoque des blocs d'écriture sur les mêmes lignes (blocs? Tables?).

Gardez à l'esprit, les machines modernes ont beaucoup de bélier. Un ensemble de résultats d'un million de lignes n'est généralement pas un gros problème. Même si chaque rangée est assez importante à 1 Ko, ce n'est que 1 Go de RAM plus frais.

Si vous allez traiter des millions de rangées de blobs, vous voulez peut-être que mysql_use_result - ou si vous souhaitez sélectionner ces lignes en morceaux avec des utilisations progressives de limite x, y .

Voir mysql_use_result et mysql_store_result dans perdc dbd :: mySQL pour plus de détails.


1 commentaires

+1, ne savait pas que DBD :: MySQL fait ça. Cependant, votre commentaire que vous ne devriez pas m'occuper sauf si vous êtes en danger d'appauvrissement de RAM est un mauvais conseil - en règle générale, vous ne devez obtenir que les données dont vous avez besoin et si vous n'avez pas besoin de des lignes de plusieurs millions (et que vous ne le faites pas rarement), Vous ne devriez pas les faire tous. Une telle approche ruinera une évolutivité au-delà de la réparation (la situation est un peu meilleure si la bibliothèque met en cache au niveau de l'application et non au niveau de la session, mais toujours pas bon - si ce cache est souvent invalidé, vous récupérez plusieurs fois 1 Go de données dans lesquelles vous avez besoin. beaucoup moins)