J'ai une table MYSQL InnoDBtable
avec les colonnes suivantes (les noms des tables et des colonnes ont été modifiés) :
où rel_ab
是描述给定日期 2 个变量 var_a
和 var_b
之间关系的列。 (var_a
和 var_b
fait référence à différents tableaux)
Les données sont téléchargées par lots chaque jour, totalisant environ 7 millions de lignes par jour. Le problème était qu’après seulement quelques semaines, le téléchargement de chaque nouveau lot quotidien commençait à prendre des heures. De toute évidence, nous devons améliorer la conception de notre table. Voici quelques détails supplémentaires sur notre formulaire.
COMPRESSION="zlib"
. var_a
和 var_b
.
的查询 SELECT * FROM table WHERE date =
. La sélection ne prend que quelques minutes. var_a
和 var_b
. df.to_sql('temp', con, if_exists='replace', index=False, method='multi')
, où nous insérons ignorer temp< /code> à df.to_sql('temp', con, if_exists='replace', index=False, method='multi')
上传,我们在其中插入忽略 < code>temp
到 table
,然后删除 temp
, puis supprimez temp
. Je prévois donc de faire au moins une des opérations suivantes :
var_a
和 var_b
et comptez sur le processus de téléchargement des données pour tout faire correctement. En effet, aucun des deux index n'améliore réellement la vitesse des requêtes dans notre cas d'utilisation. table_230501
的表,其中包含 var_a
、var_b
、rel_ab
. En effet, nous ne sélectionnons qu'une seule date à la fois. Je sais que la première solution peut menacer l'intégrité des données et que la seconde solution va gâcher notre architecture. D'après mon expérience limitée, je n'ai jamais entendu parler de la deuxième option non plus et je ne trouve aucun exemple de cette conception en ligne. L’une de ces options constitue-t-elle une solution raisonnable ? Les deux augmenteront les vitesses de téléchargement et réduiront l’utilisation du disque, mais les deux ont leurs inconvénients. Sinon, quels autres moyens existe-t-il pour augmenter la vitesse de téléchargement ?
EDIT : Le mien SHOW CREATE TABLE
devrait ressembler à
CREATE TABLE table ( date date NOT NULL, var_a int NOT NULL, var_b int NOT NULL, rel_ab decimal(19,16) NOT NULL, PRIMARY KEY (date,`var_a`,`var_b`), KEY a_idx (var_a), KEY b_idx (var_b), CONSTRAINT a FOREIGN KEY (var_a) REFERENCES other_table_a (var_a) ON DELETE RESTRICT ON UPDATE CASCADE, CONSTRAINT b FOREIGN KEY (var_b) REFERENCES other_table_b (var_b) ON DELETE RESTRICT ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMPRESSION="zlib"
Il existe quelques solutions potentielles qui peuvent vous aider à améliorer la vitesse de téléchargement de vos tables MySQL :
Supprimez les index sur var_a et var_b : puisque vous n'utilisez pas ces index pour accélérer les requêtes, leur suppression peut aider à accélérer le processus de téléchargement. Cependant, si vous utilisez des contraintes de clé étrangère, il est généralement recommandé de conserver les index sur les colonnes appartenant à la clé étrangère.
Partitionnez la table par date : le partitionnement contribue à améliorer les performances des requêtes car il permet à la base de données d'analyser uniquement les partitions pertinentes pour une requête donnée. Cependant, cela rend également la maintenance et les sauvegardes plus complexes, ce qui peut ne pas être nécessaire si vos requêtes fonctionnent déjà bien.
Utilisez la méthode d'insertion en masse : au lieu d'insérer des lignes individuelles à l'aide de df.to_sql, vous pouvez essayer d'utiliser une méthode d'insertion en masse telle que LOAD DATA INFILE ou l'API d'insertion en masse MySQL. C'est plus rapide que l'insertion individuelle, surtout si vous pouvez télécharger les données par lots plutôt qu'une ligne à la fois.
Utilisez un algorithme de compression différent : vous utilisez actuellement la compression zlib, mais il existe d'autres algorithmes de compression qui peuvent être plus rapides ou plus efficaces pour vos données. Vous pouvez essayer différentes options de compression pour voir si elles améliorent les vitesses de téléchargement.
Augmentez les ressources du serveur : si vous disposez du budget et des ressources, la mise à niveau du matériel du serveur ou l'augmentation du nombre de serveurs peut aider à augmenter les vitesses de téléchargement. Ce n'est peut-être pas une option viable pour tout le monde, mais cela vaut la peine d'y réfléchir si vous avez épuisé vos autres options.
En ce qui concerne l'option suggérée, la suppression des contraintes de clé étrangère peut entraîner des problèmes d'intégrité des données, je ne recommande donc pas cette approche. Si votre requête rencontre déjà des problèmes de performances, le partitionnement par date peut être une bonne solution, mais si votre requête s'exécute déjà rapidement, cela n'est peut-être pas nécessaire.
Pour accélérer les téléchargements, supprimez-les. Sérieusement, si la seule chose que vous faites est d'obtenir exactement le contenu d'un fichier à une certaine date, pourquoi mettre les données dans un tableau ? (Votre commentaire souligne qu'un seul fichier est en fait constitué de plusieurs fichiers. Cela pourrait être une bonne idée de les combiner d'abord.)
Si vous avez vraiment besoin des données du tableau, discutons-en...
显示创建表
; il se peut que certaines subtilités manquent dans ce que vous fournissez.加载数据
? J'espère ne pas insérer une ligne à la fois. Je ne sais pas comment fonctionnent les pandas. (Vous ne savez pas non plus comment fonctionnent les 99 autres packages qui « simplifient » l'accès à MySQL.) Veuillez comprendre ce qu'il fait dans les coulisses. Vous devrez peut-être contourner Pandas pour obtenir de meilleures performances. Le chargement en vrac est au moins 10 fois plus rapide que le chargement ligne par ligne.FLOAT
?MEDIUMINT [UNSIGNED]
Économisez au moins 7 Mo par jour.Plusieurs tables « identiques » sont toujours imprudentes. Une table, c'est toujours mieux. Cependant, comme suggéré ci-dessus, une table nulle est toujours préférable.