Mysql
 sql >> Base de données >  >> RDS >> Mysql

Cas d'utilisation MySQL `FORCE INDEX` ?

J'ai remarqué que FORCE INDEX aide lorsque vous avez plusieurs jointures et sous-requêtes sur des champs VARCHAR où le FK et la valeur référencée ne sont pas la clé primaire, tout en ayant en même temps une clause where sur un champ DATE.

Quelque chose comme :

SELECT NAME, a.reference_no, i.value, p.value FROM customers AS c
INNER JOIN accounts AS a ON c.id = a.customer_id
INNER JOIN invoices AS i ON i.reference_no = a.reference_no
INNER JOIN payments AS p ON p.invoice_no = i.invoice_no
WHERE payments.date >= '2011-09-01' AND DATE < '2011-10-01';

mysql utilisera toujours les PK et FK, où vous le feriez pour utiliser l'index payment_date sur la table des paiements en premier car c'est le plus grand. Donc un FORCE INDEX(payment_date) sur la table des paiements, une jointure aiderait beaucoup.

Ceci est un exemple tiré de la base de données de facturation tierce que nous utilisons au travail. Nous avons eu d'énormes problèmes d'optimisation, et FORCE INDEX a fait le travail la plupart du temps. Habituellement, nous trouvions les requêtes lentes avec mysqladmin, les testions avec FORCE INDEX et les envoyions aux fournisseurs pour les réécrire dans le code source de l'application.

Voici les quatre tableaux pour mieux appréhender l'exemple :

CREATE TABLE `customers` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(100) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

CREATE TABLE `accounts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `customer_id` int(11) NOT NULL,
  `reference_no` varchar(10) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `reference_no_uniq` (`reference_no`),
  KEY `FK_accounts` (`customer_id`),
  CONSTRAINT `FK_accounts` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;

CREATE TABLE `invoices` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `reference_no` varchar(10) NOT NULL,
  `invoice_no` varchar(10) NOT NULL,
  `value` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `invoice_no_uniq` (`invoice_no`),
  KEY `FK_invoices` (`reference_no`),
  CONSTRAINT `FK_invoices` FOREIGN KEY (`reference_no`) REFERENCES `accounts` (`reference_no`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;

CREATE TABLE `payments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `invoice_no` varchar(10) NOT NULL,
  `value` int(11) NOT NULL,
  `date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_payments` (`invoice_no`),
  KEY `payment_date` (`date`),
  CONSTRAINT `FK_payments` FOREIGN KEY (`invoice_no`) REFERENCES `invoices` (`invoice_no`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;