Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL `FORCE INDEX` Anwendungsfälle?

Mir ist aufgefallen, dass FORCE INDEX hilfreich ist, wenn Sie mehrere Verknüpfungen und Unterabfragen für VARCHAR-Felder haben, bei denen sowohl der FK als auch der referenzierte Wert nicht der Primärschlüssel sind, während Sie gleichzeitig eine where-Klausel in einem DATE-Feld haben.

Etwas wie:

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 verwendet immer die PKs und FKs, wobei Sie zuerst den Payment_date-Index in der Payments-Tabelle verwenden würden, da er der größte ist. Also ein FORCE INDEX(payment_date) an der Zahlungstabelle teilnehmen würde sehr helfen.

Dies ist ein Beispiel aus der Abrechnungsdatenbank eines Drittanbieters, die wir bei der Arbeit verwenden. Wir hatten große Probleme mit der Optimierung, und FORCE INDEX hat die meiste Zeit die Arbeit erledigt. Normalerweise haben wir die langsamen Abfragen mit mysqladmin gefunden, mit FORCE INDEX getestet und an die Anbieter gesendet, um sie in den Quellcode der App umzuschreiben.

Hier sind die vier Tabellen, um das Beispiel besser in den Griff zu bekommen:

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;