sql >> Databasteknik >  >> RDS >> Mysql

Användningsfall för MySQL `FORCE INDEX`?

Jag har märkt att FORCE INDEX hjälper när du har flera kopplingar och underfrågor på VARCHAR-fält där både FK och det refererade värdet inte är primärnyckeln, samtidigt som du har where-sats i ett DATE-fält.

Något i stil med:

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 kommer alltid att använda PK och FK, där du skulle vilja använda indexet payment_date i betalningstabellen först eftersom det är det största. Alltså ett FORCE INDEX(payment_date) på betalningsbordet gå med skulle hjälpa mycket.

Detta är ett exempel från tredjepartsfaktureringsdatabasen som vi använder på jobbet. Vi hade stora problem med optimering, och FORCE INDEX gjorde jobbet för det mesta. Vanligtvis hittade vi de långsamma frågorna med mysqladmin, testade dem med FORCE INDEX och skickade dem till leverantörerna för att skriva om dem i appens källkod.

Här är de fyra tabellerna för att få bättre grepp om exemplet:

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;


  1. Skillnaden mellan NullIf() och IfNull() i SQLite

  2. SQL Server:Gör alla versaler till skiftläge/titel

  3. En titt på DBCC CHECKCONSTRAINTS och I/O

  4. Hur många rader kommer att låsas av SELECT ... BESTÄLL EFTER xxx LIMIT 1 FÖR UPPDATERING?