web-dev-qa-db-fra.com

Gestion de très grandes données avec mysql

Désolé pour le long post!

J'ai une base de données contenant environ 30 tables (moteur InnoDB). Seules deux de ces tables, à savoir "transaction" et "shift" sont assez grandes (la première a 1,5 million de lignes et shift a 23k lignes). Maintenant tout fonctionne bien et je n'ai pas de problème avec la taille actuelle de la base de données.

Cependant, nous aurons une base de données similaire (mêmes types de données, conception, ..) mais beaucoup plus volumineuse, par exemple, la table "transaction" aura environ 1 milliard d’enregistrements (environ 2,3 millions de transactions par jour) et nous réfléchissons à la façon dont nous devrions traiter un tel volume de données dans MySQL? (il est à la fois lu et écrit intensif). J'ai lu de nombreux articles sur le sujet pour voir si Mysql (et plus particulièrement le moteur InnoDB) fonctionnait bien avec des milliards de disques, mais j'ai quand même quelques questions. Certains de ces articles liés que j'ai lus sont les suivants:

Ce que j'ai compris jusqu'à présent pour améliorer les performances des très grandes tables:

  1. (pour les tables innoDB ce qui est mon cas) augmentant le innodb_buffer_pool_size (par exemple, jusqu’à 80% de RAM). De plus, j'ai trouvé d'autres paramètres de réglage des performances MySQL ici dans le blog percona
  2. avoir des index appropriés sur la table (en utilisant EXPLAN sur les requêtes)
  3. partitionner la table
  4. MySQL Sharding ou clustering

Voici mes questions/confusions:

  • À propos du partitionnement, je doute que nous devions ou non l'utiliser. D'un côté, de nombreuses personnes ont suggéré d'améliorer les performances lorsque la table est très grande. Par ailleurs, j'ai lu de nombreux articles disant que cela n'améliorait pas les performances des requêtes et que les requêtes ne s'exécutaient pas plus rapidement (par exemple, ici et ici ). De plus, j'ai lu dans Manuel de référence MySQL que les clés étrangères InnoDB et le partitionnement MySQL ne sont pas compatibles (nous avons des clés étrangères).

  • En ce qui concerne les index, ils fonctionnent bien pour l'instant, mais d'après ce que j'ai compris, l'indexation est plus restrictive pour les très grands tableaux (comme Kevin Bedell l'a mentionné dans sa réponse ici ). De plus, les index accélèrent les lectures tout en ralentissant l'écriture (insertion/mise à jour). Donc, pour le nouveau projet similaire pour lequel nous aurons une base de données volumineuse, devrions-nous d'abord insérer/charger toutes les données, puis créer des index? (pour accélérer l'insertion)

  • Si nous ne pouvons pas utiliser le partitionnement pour notre grande table (table "transaction"), quelle autre option pour améliorer les performances? (sauf les paramètres variables de MySQl tels que innodb_buffer_pool_size). Devrions-nous utiliser des grappes Mysql? (nous avons aussi beaucoup de jointures)

MODIFIER

Ceci est la déclaration show create table De notre plus grande table nommée "transaction":

  CREATE TABLE `transaction` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `terminal_transaction_id` int(11) NOT NULL,
 `fuel_terminal_id` int(11) NOT NULL,
 `fuel_terminal_serial` int(11) NOT NULL,
 `xboard_id` int(11) NOT NULL,
 `gas_station_id` int(11) NOT NULL,
 `operator_id` text NOT NULL,
 `shift_id` int(11) NOT NULL,
 `xboard_total_counter` int(11) NOT NULL,
 `fuel_type` int(11) NOT NULL,
 `start_fuel_time` int(11) NOT NULL,
 `end_fuel_time` int(11) DEFAULT NULL,
 `preset_amount` int(11) NOT NULL,
 `actual_amount` int(11) DEFAULT NULL,
 `fuel_cost` int(11) DEFAULT NULL,
 `payment_cost` int(11) DEFAULT NULL,
 `purchase_type` int(11) NOT NULL,
 `payment_ref_id` text,
 `unit_fuel_price` int(11) NOT NULL,
 `fuel_status_id` int(11) DEFAULT NULL,
 `fuel_mode_id` int(11) NOT NULL,
 `payment_result` int(11) NOT NULL,
 `card_pan` text,
 `state` int(11) DEFAULT NULL,
 `totalizer` int(11) NOT NULL DEFAULT '0',
 `shift_start_time` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `terminal_transaction_id` (`terminal_transaction_id`,`fuel_terminal_id`,`start_fuel_time`) USING BTREE,
 KEY `start_fuel_time_idx` (`start_fuel_time`),
 KEY `fuel_terminal_idx` (`fuel_terminal_id`),
 KEY `xboard_idx` (`xboard_id`),
 KEY `gas_station_id` (`gas_station_id`) USING BTREE,
 KEY `purchase_type` (`purchase_type`) USING BTREE,
 KEY `shift_start_time` (`shift_start_time`) USING BTREE,
 KEY `fuel_type` (`fuel_type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1665335 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT

Merci pour votre temps,

28
mOna
  • MySQL peut-il raisonnablement effectuer des requêtes sur des milliards de lignes? - MySQL peut "gérer" des milliards de lignes. "Raisonnablement" dépend des requêtes; voyons les.

  • InnoDB (MySQL 5.5.8) est-il le bon choix pour plusieurs milliards de lignes? - La version 5.7 a quelques améliorations, mais la version 5.5 est assez bonne, malgré le fait presque 6 8 ans, et sur le point de ne plus être pris en charge.

  • Meilleur magasin de données pour des milliards de lignes - Si vous voulez dire 'Moteur', alors InnoDB.

  • Quelle taille une base de données MySQL peut-elle atteindre avant que les performances ne commencent à se dégrader - Là encore, cela dépend des requêtes. Je peux vous montrer une table de rangée 1K qui va s'effondrer; J'ai travaillé avec des tables de plusieurs milliards de lignes.

  • Pourquoi MySQL pourrait être lent avec de grandes tables? - les balayages de plage mènent aux E/S, qui sont la partie lente.

  • Mysql peut-il gérer des tables contenant environ 300 millions d’enregistrements? - encore, oui. La limite est d'environ un billion de lignes.

  • (pour les tables innoDB, ce qui est mon cas), augmentez innodb_buffer_pool_size (par exemple, jusqu’à 80% de la RAM). En outre, j'ai trouvé d'autres paramètres de réglage des performances MySQL dans le blog percona - oui

  • avoir des index appropriés sur la table (en utilisant EXPLAN sur les requêtes) - eh bien, voyons-les. De nombreuses erreurs peuvent être commises dans ce domaine critique .

  • partitionner la table - "Le partitionnement n'est pas une panacée!" Je harpe sur cela dans mon blog

  • MySQL Sharding - Actuellement, c'est du bricolage

  • Clustering MySQL - Actuellement, la meilleure réponse est une option basée sur Galera (PXC, MariaDB 10, DIY avec Oracle). La "réplication de groupe" d'Oracle est un candidat viable.

  • Le partitionnement ne supporte pas FOREIGN KEY ou "global" UNIQUE.

  • Les UUID, à l'échelle dont vous parlez, ne feront pas que ralentir le système, mais le tueront en réalité. UUID de type 1 peut constituer une solution de contournement.

  • Vitesse d'insertion et d'indexation - Il y a trop de variations pour donner une seule réponse. Voyons votre tentative CREATE TABLE et comment vous envisagez d’alimenter les données.

  • Beaucoup de jointures - "Normaliser, mais ne pas trop normaliser." En particulier, ne normalisez pas les dates/heures, les flottants ou les autres valeurs "continues".

  • Construisez des tableaux récapitulatifs

  • 2,3 millions de transactions par jour - S'il s'agit de 2,3 M insère (30/s), le problème de performances est faible. Si plus complexe, RAID, SSD, traitement par lots, etc. peuvent être nécessaires.

  • traiter avec un tel volume de données - Si la plupart des activités se font avec les lignes "récentes", alors le pool de tampons tamponnera joliment "en cache" l'activité, évitant ainsi les E/S. Si l'activité est "aléatoire", alors MySQL (ou n'importe qui sinon) aura des problèmes d'E/S.

  • Réduire les types de données aide dans un tableau comme le vôtre. Je doute que vous ayez besoin de 4 octets pour spécifier fuel_type. Il existe plusieurs approches à un octet.

41
Rick James

Lors de la collecte de milliards de lignes, il est préférable (lorsque cela est possible) de consolider, de traiter, de résumer, quelles que soient les données, avant le stockage. Conservez les données brutes dans un fichier si vous pensez devoir y revenir.

Cela éliminera la plupart de vos questions et préoccupations et accélérera le traitement.

2
Rick James