Je travaille sur une application qui implique beaucoup d'écritures de base de données, environ 70% d'insertions et 30% de lectures. Ce ratio comprendrait également les mises à jour que je considère comme une lecture et une écriture. Grâce aux instructions d'insertion, plusieurs clients insèrent des données dans la base de données via l'instruction d'insertion ci-dessous:
$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");
La question est de savoir si je dois utiliser insert_delay ou utiliser mysqli_multi_query mécanisme car insert utilise ~ 100% cpu sur le serveur. J'utilise le moteur InnoDB sur ma base de données donc l'insertion différée n'est pas possible. L'insertion sur le serveur est ~ 36k/h et 99,89% de lecture, j'utilise également l'instruction select là récupérer les données sept fois en une seule requête , cette requête prend 150 secondes sur le serveur pour s'exécuter. Quel type de technique ou de mécanisme puis-je utiliser pour cette tâche? La mémoire de mon serveur est de 2 Go, dois-je étendre la mémoire?. Jetez un oeil sur ce problème, toute suggestion me sera reconnaissante.
Structure du tableau:
+-----------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user | varchar(100) | NO | | NULL | |
| uniq_name | varchar(200) | NO | | NULL | |
| ad_name | varchar(200) | NO | | NULL | |
| ad_delay_time | int(11) | NO | | NULL | |
| track_time | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
+-----------------+--------------+------+-----+-------------------+----------------+
Ma base de données présente l'état, elle affiche 41 000 insertions (écritures), ce qui est très lent pour ma base de données.
Puisque vous avez plus d'écrit puis de lecture, je voudrais recommander ce qui suit
Puisque InnoDB ne prend pas en charge INSERT DELAYED , l'utilisation d'un grand pool de tampons InnoDB est la chose la plus proche que vous pouvez obtenir pour INSERT DELAYED. Tous les DML (INSERT, UPDATE et DELETE) seraient mis en cache dans le pool de tampons InnoDB. Les informations transactionnelles pour les écritures sont écrites immédiatement dans les journaux de rétablissement (ib_logfile0, ib_logfile1). Les écritures qui sont publiées dans le pool de tampons sont périodiquement vidées de la mémoire sur le disque via ibdata1 (InsertBuffer pour les index secondaires, tampon d'écriture double). Plus le pool de tampons est grand, plus la quantité d'inserts peut être mise en cache. Dans un système avec 8 Go ou plus de RAM, utilisez 75 à 80% de la RAM comme innodb_buffer_pool_size. Dans un système avec très peu de RAM, 25% (pour accueillir le système d'exploitation).
CAVEAT: Vous pouvez définir innodb_doublewrite sur 0 pour accélérer encore plus les écritures, mais au risque d'intégrité des données. Vous pouvez également accélérer les choses en définissant innodb_flush_method sur O_DIRECT pour empêcher la mise en cache d'InnoDB sur le système d'exploitation.
Par défaut, les journaux de rétablissement sont nommés ib_logfile0 et ib_logfile1 et auraient 5 Mo chacun. La taille doit correspondre à 25% de la taille innodb_buffer_pool_size. Si les journaux de rétablissement existent déjà, ajoutez le nouveau paramètre dans my.cnf, arrêtez mysql, supprimez-les et redémarrez mysql .
Le tampon de journal contient les modifications de RAM avant de les vider dans les journaux de rétablissement. La valeur par défaut est 8 Mo. Plus le tampon de journal est grand, moins les E/S de disque. Soyez prudent avec les transactions très volumineuses, car cela peut ralentir les COMMITs de quelques millisecondes.
MySQL 5.5 et le plug-in MySQL 5.1 InnoDB ont des paramètres permettant au moteur de stockage InnoDB d'accéder à plusieurs processeurs. Voici les options que vous devez définir:
Si vous avez MySQL 5.0, passez à MySQL 5.5. Si vous avez MySQL 5.1.37 ou une version antérieure, passez à MySQL 5.5. Si vous avez MySQL 5.1.38 ou supérieur et que vous souhaitez rester dans MySQL 5.1, installez le plug-in InnoDB. De cette façon, vous pouvez profiter de tous les processeurs pour InnoDB.
INT (2) utilise toujours 4 octets - peut-être que vous vouliez dire TINYINT UNSIGNED?
Combien de valeurs différentes dans setno? S'il est petit, la KEY (setno) ne sera jamais utilisée. INSERTing doit mettre à jour cet index; retirer la CLÉ accélérera EN INSÉRER.
CHAR (10) - flag
est-il toujours composé de 10 caractères? Et en utf8? Peut-être pourriez-vous utiliser le drapeau VARCHAR (10) CHARACTER SET ascii
Batch vos inserts - 100 à la fois fonctionneront 10 fois plus vite. (Au-delà de 100, les "rendements décroissants" augmentent.)
Quelle est la valeur de l'autocommit? Enveloppez-vous chaque INSERT dans BEGIN ... COMMIT? Quelle est la valeur de innodb_flush_log_at_trx_commit?
Configurez une file d'attente. L'application écrirait dans une file d'attente 1 ligne à la fois, puis retirerait les lignes et les insérerait dans une base de données par lots en fonction du nombre de lignes ou du temps écoulé depuis la dernière insertion.
J'ai vu où le regroupement des inserts 10 000 à la fois est le plus rapide, vous devez donc tester pour trouver un endroit idéal.
Vous pouvez créer votre propre système de file d'attente simple ou utiliser un système existant. Voici quelques exemples: HornetQ et File :: Queue . Voici un article sur SE listant d'autres bonnes options: Files d'attente de messages en Perl, php, python .