web-dev-qa-db-fra.com

Besoin de suggestions pour la meilleure façon d'archiver les tables MySQL (Innodb)

problème: J'ai deux tables assez grandes. Une table "murale" pour les messages entre utilisateurs avec 9 millions de lignes à 2 Go et une table de chapitre à 2 millions de lignes et 18 Go. Je veux garder le nombre de lignes actives pour la table "Wall" petit pendant que je veux diminuer la taille de la table de chapitre. J'ai commis l'erreur de ne pas comprimer les données de texte pour commencer et je voudrais commencer à comprimer les données dans les archives.

Pour la table 'Wall', je pense que tout plus vieux qu'une certaine identification murale sera transférée et comprimée à un "wall_archive". Toute personne désireuse d'afficher des messages plus âgés sera juste à juste titre de lien "Afficher les archives" où les plus anciennes postes utilisent la table d'archives. Ensuite, je gère un travail de cron pour le faire de temps en temps et que le dernier identifiant mural archivé sera stocké quelque part pour référence. Est-ce que je vais la bonne direction ici?

Je ne suis pas si sûr comment garder la table "chapitre" gérable. Peut-être que c'est moins archivé et plus besoin de partitionner la table (ou les deux). Mais quelle est la meilleure façon de faire ça? Je pensais séparer des identifiants de "histoire" dans les chances et à vaincre et à diviser le chapitre en deux tables, mais je vais courir dans le même problème sur la route. Ou je peux archiver des histoires modifiées avant une certaine date. Ou avant une pièce d'identité de l'histoire. Toute suggestion pour une solution évolutive?

Enfin, comment devrais-je continuer à compresser des données de texte? Devrais-je utiliser la fonction GZCompress PHP au niveau 9 pour stocker des données de texte dans une colonne blob, puis gzuncompressez les données sur la récupération? Ou devrais-je utiliser la compresse de MySQL/dissocaliser les fonctions? Je suis penché vers l'utilisation PHP au cas où je séparerai le ou les serveurs Web du serveur DB où je peux avoir PHP faire les processus de compression au lieu de Le serveur DB plus précieux, mais j'aimerais savoir quelles sont les meilleures pratiques.

Considérations: Je devrai encore accéder facilement aux anciens "chapitres". Les données "murales" peuvent être placées dans un stockage plus lent si nécessaire, mais ce n'est pas nécessaire pour le moment.

Environnement: 6 Core AMD Opteron, 16 Go de RAM, 256 Go SSD pour MySQL, PerCona Server 5.5, Apache, Centos 6, PHP 5.3, Innodb_File_Per_Table est activé, base de données et WebServer fonctionne sur la même machine, la taille totale de la base de données est de 30 Go, toutes les tables sont innodub

schémas:

CREATE TABLE `wall` (
  `id_wall` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `id_author` int(10) unsigned NOT NULL 
     COMMENT 'wall''s owner',
  `id_user` int(10) unsigned NOT NULL DEFAULT '0'
     COMMENT 'user that wrote the comment',
  `comment` text NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY (`id_wall`),
  KEY `id_user` (`id_user`),
  KEY `id_author` (`id_author`)
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8
  COMMENT='User profile wall'
  AUTO_INCREMENT=9710655 ;

CREATE TABLE IF NOT EXISTS `chapter` (
  `id_story` int(11) unsigned NOT NULL,
  `id_chapter` int(11) unsigned NOT NULL DEFAULT '0',
  `title` varchar(255) NOT NULL,
  `main_image` varchar(2047) DEFAULT NULL,
  `body` mediumtext,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  `is_not_shown` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id_story`,`id_chapter`)
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8
  ROW_FORMAT=DYNAMIC
  COMMENT='Story content by chapter';

ALTER TABLE `chapter`
  ADD CONSTRAINT `chapter_ibfk_1` 
    FOREIGN KEY (`id_story`) 
    REFERENCES `story` (`id_story`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE;
6
havokado

Pour compresser ...

Faites-le dans le client; Cela conduira à moins de trafic entre client et serveur. (OK, ils sont sur la même machine, ce n'est donc pas une grande partie d'un problème.)

Utilisez GZCompress PHP, Gzuncomress; Ne vous inquiétez pas du niveau de compression. Attendez-vous à une compression de 3: 1 pour un texte régulier.

Oui, le MODIODEXT devrait être moyenblob.

Ne pas "archiver" anciennes données; Vous n'avez pas justifié le besoin de celui-ci (encore). La mise en cache s'occupera généralement de faire de "récents" chapitres plus rapidement.

Découvrez Facebook et Percona pour "Aller en ligne".

innodb_buffer_pool_size devrait être d'environ 70% de disponible RAM.

2
Rick James

Performance

Je développerais des analyses qui me disent à quelle fréquence les données plus anciennes sont accessibles et par quels intervalles de date. Si très peu de gens regardent quelque chose de plus de 1 mois, vos options sont nombreuses. Si c'est tout au long de la planche, ce sera une stratégie différente.

Faisons prétendre que le contenu de plus d'un mois n'est accessible que de temps en temps, disons <2% des demandes. Deux options disponibles pour vous incluent: partitionnement et Sharding horizontal , à la fois par date. Avec partitionnement, vous simplement partition par plage à l'aide du champ "créé" de votre table. Avec une tommande horizontale, vous faites la même chose, sauf en utilisant un travail ou un événement Cron pour créer une nouvelle version périodique de votre table, puis migrer les lignes vers la périodique tableau. Avec un frisson horizontal, vous peut Utilisation [~ # ~] Union [~ # ~] Déclarations pour couvrir plusieurs tables .

Le partitionnement aura peu ou aucun effet sur votre modèle de données. La tommande nécessitera une intelligence de modèle de données.

4
randomx