Ich bin neu in Performance-Tuning in MySQL & brauchen Sie Ihre Hilfe bezüglich einer Ansicht, die später eine Tabelle in unserem Design ersetzen wird.Performance-Probleme mit einer geordneten Ansicht in MySQL
Die Tabelle wird Benutzer und hat folgende Attribute genannt ersetzt: Die users2 Ansicht hat folgende Attribute:
Wenn ich ein normaler auf beiden Objekte SELECT ausführen, sie zur gleichen Zeit reagieren:
SELECT *
FROM `users`
SELECT *
FROM `users2`
Aber eine geordnete Version dieser Abfragen führen zu einer unterschiedlichen performa nce: Der Tisch ist ein wenig langsamer (dauert weniger als zwei Sekunden), die Ansicht benötigen etwa zehnmal diesmal:
SELECT *
FROM `users`
ORDER BY `lastName`, `firstName`
SELECT *
FROM `users2`
ORDER BY `lastName`, `firstName`
Um den Grund herauszufinden, ich die beiden Kommentare ERKLÄREN lassen:
Offensichtlich ein ALL auf dem Tisch 'ein' (Adressen) auf dem Attribut Countries_ID ist trou machen Ich habe folgendes gemacht:
ALTER TABLE addresses ADD INDEX (Countries_ID);
Dieser Index hat überhaupt nichts geändert. Also, ich frage Sie nach Ihrer Meinung, was besser gemacht werden kann.
Hinweis 1: Gibt es eine Möglichkeit zum Erstellen eines Index für temporäre Spalte Countries_ID_2? Hinweis 2: Die users2 Ansicht mit der folgenden SQL-Abfrage erstellt wurde:
CREATE OR REPLACE VIEW users2 AS
(SELECT p.username
, p.password
, p.firstName
, p.lastName
, p.eMail AS email
, a.settlement AS city
, s.name AS country
, pl.languages
, p.description
, p.ID AS ID
, p.phone1
, p.phone2
, CONCAT_WS(' ', a.street, a.addition) AS address
, p.status
, p.publicMail
, ad.name AS Betreuer
FROM addresses a
INNER JOIN addresses_have_persons ap ON a.ID = ap.Addresses_ID
INNER JOIN countries c ON a.Countries_ID = c.ID
INNER JOIN persons p ON a.ID = p.addressID
AND ap.Persons_ID = p.ID
INNER JOIN states s ON a.States_ID = s.ID
INNER JOIN persons_language pl ON p.ID = pl.ID
LEFT JOIN advisors ad ON p.advisorID = ad.ID
-- LEFT JOIN titles t ON t.ID = ad.titleID
);
Hinweis 3: Obwohl viele Felder in den Personen Tabelle ist NULL, gibt es nicht eine einzige Reihe ist, wo Diese Felder sind insgesamt NULL.
EDIT:
CREATE OR REPLACE VIEW persons_language AS
(SELECT lp.Persons_ID AS ID
, GROUP_CONCAT(DISTINCT l.name ORDER BY l.name SEPARATOR ', ') AS languages
FROM languages l
, languages_have_persons lp
WHERE l.ID = lp.Languages_ID
GROUP BY lp.Persons_ID);
Ohne die ORDER BY werden die Sprachnamen nicht alphabetisch geordnet, die ich zur Zeit möchten. Vielleicht könnten wir uns entscheiden, sie in beliebiger Reihenfolge zu bekommen, aber wir werden sehen.
Derzeit habe ich die folgenden Änderungen ohne Leistungsverbesserung:
ALTER TABLE addresses ADD INDEX (Countries_ID);
ALTER TABLE addresses ADD INDEX (States_ID);
ALTER TABLE addresses_have_persons ADD INDEX (Addresses_ID);
ALTER TABLE languages ADD INDEX (name);
ALTER TABLE persons ADD INDEX (addressID);
ALTER TABLE persons ADD INDEX (address2ID);
ALTER TABLE persons ADD INDEX (address3ID);
ALTER TABLE persons ADD INDEX (advisorID);
EDIT 2:
ich dieses Problem diskutieren auch auf einer anderen Website.Die Diskussionen lassen Sie mich es folgende Änderungen tun näher zu sein, in die dritte Normalform:
CREATE OR REPLACE TABLE accounts
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, username VARCHAR(50) NOT NULL UNIQUE
, password VARCHAR(255) NOT NULL
, eMail VARCHAR(100) NOT NULL
, Persons_ID INT NOT NULL
);
INSERT INTO accounts (username, password, eMail, Persons_ID)
SELECT username, password, eMail, ID
FROM persons;
Die Tabelle Personen enthält nur das Nötigste und hat die folgende Struktur jetzt:
die neue Tabelle persons_information trägt alle zusätzlichen Informationen:
ich neu erstellt die users2 mit dem folgenden Befehl:
CREATE OR REPLACE VIEW users2 AS
(SELECT ac.username
, ac.password
, p.firstName
, p.lastName
, ac.eMail AS email
, adr.settlement AS city
, s.name AS country
, pl.languages
, pi.description
, ac.Persons_ID AS ID
, pi.phone1
, pi.phone2
, CONCAT_WS(' ', adr.street, adr.addition) AS address
, p.status
, pi.publicMail
, adv.name AS Betreuer
FROM accounts ac
INNER JOIN persons p ON ac.Persons_ID = p.ID
INNER JOIN persons_information pi ON p.ID = pi.ID
INNER JOIN addresses adr ON adr.ID = pi.addressID
INNER JOIN addresses_have_persons ap ON adr.ID = ap.Addresses_ID
AND ap.Persons_ID = p.ID
INNER JOIN countries c ON adr.Countries_ID = c.ID
INNER JOIN states s ON adr.States_ID = s.ID
INNER JOIN persons_language pl ON p.ID = pl.ID
LEFT JOIN advisors adv ON pi.advisorID = adv.ID
-- LEFT JOIN titles t ON t.ID = adv.titleID
);
Die SELECT _ VON users2 ist schnell, aber wenn ich eine ORDER BY nachName hinzufügen, vorName, dauert es etwa 25 Sekunden, um die Antwort zu erhalten.
Hier sind die Ergebnisse der * EXPLAIN SELECT * FROM users2 * Befehl:
Und hier für den anderen Befehl:
ich auch (wieder) erstellt folgende Indizes:
ALTER TABLE addresses ADD INDEX (Countries_ID);
ALTER TABLE addresses ADD INDEX (States_ID);
ALTER TABLE addresses_have_persons ADD INDEX (Persons_ID);
ALTER TABLE languages ADD INDEX (name);
ALTER TABLE persons_information ADD INDEX (addressID);
ALTER TABLE persons_information ADD INDEX (address2ID);
ALTER TABLE persons_information ADD INDEX (address3ID);
ALTER TABLE persons_information ADD INDEX (advisorID);
ich denke, ein Grund für das Problem ist die persons_language Ansicht, die erstellt wird, wie folgt:
CREATE OR REPLACE VIEW persons_language AS
(SELECT lp.Persons_ID AS ID
, GROUP_CONCAT(DISTINCT l.name ORDER BY l.name SEPARATOR ', ') AS languages
FROM languages l
INNER JOIN languages_have_persons lp ON l.ID = lp.Languages_ID
GROUP BY lp.Persons_ID);
EDIT 4: Für Interessenten, ich die EXPLAIN für die persons_language Ansicht hinzufügen Nach der Datenbank heutigen Sitzung beschlossen wir, alle Objekte löschen in Bezug auf die Adressinformationen & erstellt die Ansicht mit
CREATE OR REPLACE VIEW `users2` AS
(SELECT ac.username
, ac.password
, p.firstName
, p.lastName
, ac.eMail AS email
, pl.languages
, pi.description
, ac.Persons_ID AS ID
, pi.phone1
, pi.phone2
, p.status
, pi.publicMail
, adv.name AS Betreuer
FROM accounts ac
INNER JOIN persons p ON ac.Persons_ID = p.ID
INNER JOIN persons_information pi ON p.ID = pi.ID
INNER JOIN persons_language pl ON p.ID = pl.ID
INNER JOIN advisors adv ON pi.advisorID = adv.ID
WHERE ac.password IS NOT NULL
);
I erstellt auch einen Index mit
CREATE INDEX LanguagesPersonsIndex ON `languages_have_persons` (`Languages_ID`, `Persons_ID`);
Dem EXPLAIN Befehl zeigt, dass die neue Indizes in Gebrauch ist, und dass die Verzögerung nach einem SELECT mit einem ORDER BY Klausel mit der neuen, kleineren Ansicht ist, ungefähr 18 s. Hier ist das neue Ergebnis: Meine Frage ist: Was könnte ich mehr tun, um die Leistung zu verbessern?
Vielen Dank für Ihre Antwort, @Renato Tarso! Leider habe ich eine ORDER BY in einer Ansicht, die notwendig ist. Siehe die obige Frage. Alle Auftrags-/Gruppierungs-/Beziehungsattribute sind Schlüssel. – Sae1962
"... sind Primärschlüssel" (Natürlich, keine Primärschlüssel für Ansichten Advisors & Persons_language) – Sae1962
@ Sae1962, überprüfen Sie meine Antwort ändert. Ich hoffe es ist nützlich. Viel Glück. –