Table MySQL avec 100 000 enregistrements souvent interrogés

11

J'ai une base de données unique d'environ 100 tables pour stocker différents types d'informations.

Le tableau le plus important est notre tableau de commandes qui est utilisé pour stocker les commandes des clients et qui compte plus de 100 000 enregistrements à ce jour et en croissance.

Ce tableau est le tableau le plus interrogé de notre base de données, pour diverses parties d'informations nécessaires à partir de tableaux de bord de commande en temps réel, de statistiques, d'analyses, etc.

Je surveille régulièrement la base de données et j'active les requêtes lentes sur la base de données pour suivre les problèmes.

J'utilise des scripts comme mysqltuner pour cracher des requêtes quotidiennement.

J'utilise également mysqlsla pour recueillir des informations sur les 10 requêtes les plus lentes dans notre base de données.

sample stat
Count         : 11.48k  (30.66%)
Time          : 19.623758 s total, 1.709 ms avg, 239 µs to 2.475017 s max  (18.64%)
  95% of Time : 5.246833 s total, 481 µs avg, 239 µs to 1.095 ms max
Lock Time (s) : 14.460071 s total, 1.259 ms avg, 53 µs to 2.462555 s max  (41.38%)
  95% of Lock : 806.43 ms total, 74 µs avg, 53 µs to 137 µs max
Rows sent     : 1 avg, 0 to 9 max  (0.99%)
Rows examined : 6 avg, 1 to 28 max  (0.15%)

La plupart des requêtes les plus lentes concernent la table de commande mentionnée ci-dessus. J'utilise MyISAM comme moteur de stockage afin que les problèmes possibles puissent être:

  1. Verrouillage de table
  2. Problèmes d'indexation

Comment pourrais-je améliorer ces statistiques, j'ai l'indexation en place pour ces tables et j'ai continué à les peaufiner pour améliorer les requêtes de lecture.

Schéma de table

`orderid` int(11) NOT NULL AUTO_INCREMENT,
`cityid` tinyint(3) unsigned NOT NULL DEFAULT '1',
 `model_type` tinyint(1) unsigned DEFAULT '1',
`userid` int(11) DEFAULT NULL,
`usertype` char(1) DEFAULT NULL,
`time` time DEFAULT NULL,
`ordercode` char(8) DEFAULT NULL,
`restid` smallint(3) unsigned NOT NULL,
`areaid` smallint(3) unsigned DEFAULT NULL,
`restname` varchar(50) DEFAULT NULL,
`date` date NOT NULL,
`del_time` time NOT NULL,
`status` tinyint(3) unsigned NOT NULL,
`amount` float NOT NULL,
`deliverycharge` smallint(4) unsigned DEFAULT '0',
`tax` float NOT NULL,
`total` float NOT NULL,
`extras` varchar(255) DEFAULT NULL,
`requests` varchar(255) DEFAULT NULL,
`discount` float DEFAULT NULL,
`rdiscount` float DEFAULT NULL,
`reason` varchar(255) DEFAULT NULL,
`rest_order` tinyint(1) unsigned DEFAULT NULL,
`admin_user` varchar(25) DEFAULT NULL,
`mode` char(1) NOT NULL,
`priority_order` tinyint(1) unsigned DEFAULT '0',
`payment_mode` tinyint(1) unsigned DEFAULT '0',
`km` tinyint(3) unsigned DEFAULT NULL,
`order_type` tinyint(1) NOT NULL DEFAULT '1',
`coupon_discount` smallint(3) DEFAULT '0',
`pickup_time` time NOT NULL,
PRIMARY KEY (`orderid`),
KEY `cityid` (`cityid`),
KEY `date_3` (`date`,`status`,`mode`),
KEY `orderid` (`orderid`),
KEY `time` (`time`),
KEY `userid` (`userid`,`usertype`),
KEY `restid` (`restid`,`date`,`status`)

requête de journal lent

SELECT `a`.`orderid`, `a`.`date`, `a`.`status`, `a`.`restname`, `a`.`admin_user`, `a`.`model_type`, `b`.`name` as cityname
FROM `tk_order_queue` AS a
INNER JOIN `tk_cities` AS b ON `a`.`cityid` = `b`.`id`
WHERE `a`.`date` =  '2012-06-30'
AND `a`.`status` =  0
AND `a`.`mode` =  1
ORDER BY `a`.`orderid` desc;
Sheldon
la source
Veuillez l'exécuter SHOW CREATE TABLE orders\Get l'afficher dans la question
RolandoMySQLDBA
2
Suis-je en train de lire cela incorrectement, ou le temps de requête moyen est-il de 1,7 ms? Pourquoi diable voudriez-vous accélérer cela?
Philᵀᴹ
Je suis un peu confus quant à la raison pour laquelle cela apparaît dans les journaux de requête lents.
sheldon
@RolandoMySQLDBA j'ai attaché le schéma
sheldon
1
Ce n'est pas parce que vous avez des index sur la table que ce sont les bons index pour vos requêtes. Pourriez-vous publier quelques exemples de requêtes lentes et leur sortie EXPLAIN? De plus, à quelle fréquence le tableau des commandes est-il mis à jour?
bobwienholt

Réponses:

8

Vous devrez comparer les clauses WHERE et les instructions GROUP BY et ORDER BY de toutes vos requêtes pour vous assurer que vos index actuels peuvent les prendre en charge dans leurs plans EXPLAIN.

Hier, j'ai répondu à cette question: InnoDB vs MyISAM avec de nombreux index

Dans cette question, j'ai suggéré de faire quelque chose à la table MyISAM que vous pouvez faire aussi

ALTER TABLE orders ROW_FORMAT=Fixed;

Cela traitera tous les VARCHAR comme des CHAR. Chaque ligne aura exactement la même longueur. Cela augmentera l'espace disque de 80% à 100%. Votre tableau gonflera à la taille maximale pour la disposition des lignes multipliée par le nombre de lignes. Votre table peut doubler ou tripler de taille.

Où est l'avantage? Votre table MyISAM sera alors lue / écrite de 20% à 30% plus rapidement sans rien changer d'autre.

J'ai appris cela des pages 72,73 de MySQL Database Design and Tuning .

J'ai écrit à ce sujet dans le passé:

RolandoMySQLDBA
la source
Merci pour l'explication détaillée, oui les index ajoutés à la table sont basés sur les requêtes utilisées pour les instructions selects, group by et order by utilisées dans notre système. Ont surveillé les requêtes sans journaux d'index et mis à jour les tables en conséquence.
sheldon