MySQL-Tabelle mit 100.000 Datensätzen, die häufig abgefragt werden


11

Ich habe eine einzige Datenbank mit ungefähr 100 Tabellen, um verschiedene Arten von Informationen zu speichern.

Die wichtigste Tabelle ist unsere Auftragstabelle, in der Kundenbestellungen gespeichert werden und die derzeit über 100000 Datensätze umfasst und wächst.

Diese Tabelle ist die am häufigsten abgefragte Tabelle in unserer Datenbank für verschiedene Teile von Informationen, die von Echtzeit-Auftrags-Dashboards, Statistiken, Analysen usw. benötigt werden.

Ich überwache die Datenbank regelmäßig und habe langsame Abfragen in der Datenbank aktiviert, um Probleme zu verfolgen.

Ich benutze Skripte wie mysqltuner, um täglich Abfragen auszuspucken.

Ich benutze auch mysqlsla, um Informationen über die 10 langsamsten Abfragen in unserer Datenbank zu sammeln.

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%)

Die meisten der am langsamsten abgefragten betreffen die oben genannte Auftragstabelle. Ich verwende MyISAM als Speicher-Engine, sodass mögliche Probleme auftreten können:

  1. Tischsperre
  2. Indizierungsprobleme

Wie könnte ich diese Statistiken verbessern? Ich habe eine Indizierung für diese Tabellen eingerichtet und sie ständig optimiert, um die Leseabfragen zu verbessern.

Tabellenschema

`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`)

langsame Protokollabfrage

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;

Bitte laufen Sie SHOW CREATE TABLE orders\Gund posten Sie das in der Frage
RolandoMySQLDBA

2
Lese ich das falsch oder beträgt die durchschnittliche Abfragezeit 1,7 ms? Warum um alles in der Welt würden Sie versuchen, das zu beschleunigen?
Philᵀᴹ

Ich bin ein wenig verwirrt darüber, warum dies in den langsamen Abfrageprotokollen angezeigt wird.
Sheldon

@ RolandoMySQLDBA Ich habe das Schema angehängt
Sheldon

1
Nur weil Sie Indizes in der Tabelle haben, heißt das nicht, dass sie die richtigen Indizes für Ihre Abfragen sind. Könnten Sie einige Beispiele für langsame Abfragen und deren EXPLAIN-Ausgabe veröffentlichen? Wie oft wird die Auftragstabelle aktualisiert?
Bobwienholt

Antworten:


8

Sie müssen die WHERE-Klauseln sowie die Anweisungen GROUP BY und ORDER BY aller Ihrer Abfragen vergleichen, um sicherzustellen, dass Ihre aktuellen Indizes sie in ihren EXPLAIN-Plänen unterstützen können.

Gestern habe ich diese Frage beantwortet: InnoDB vs MyISAM mit vielen Indizes

In dieser Frage schlug ich vor, etwas an der MyISAM-Tabelle zu tun, das Sie auch tun können

ALTER TABLE orders ROW_FORMAT=Fixed;

Dadurch werden alle VARCHARs als CHARs behandelt. Jede Reihe hat genau die gleiche Länge. Dadurch wird der Speicherplatz um 80% bis 100% erhöht. Ihre Tabelle wird auf die maximale Größe für das Zeilenlayout multipliziert mit der Anzahl der Zeilen aufgebläht. Ihr Tisch kann doppelt oder dreifach groß sein.

Wo ist der Nutzen? Ihre MyISAM-Tabelle wird dann zwischen 20% und 30% schneller gelesen / geschrieben, ohne dass etwas anderes geändert wird.

Das habe ich auf den Seiten 72, 73 von MySQL Database Design and Tuning gelernt .

Ich habe darüber in der Vergangenheit geschrieben:


Vielen Dank für die ausführliche Erklärung. Ja, die der Tabelle hinzugefügten Indizes basieren auf den Abfragen, die für die in unserem System verwendeten Anweisungen select, group by und order by verwendet wurden. Ich habe die Abfragen ohne Indexprotokolle überwacht und die Tabellen entsprechend aktualisiert.
Sheldon
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.