2017-06-03 2 views
1

ich einen Suchfilter Seite in meiner Münze Webseite Umsetzung, aber es ist jetzt ganz langsam, dass ich viele Einträge haben: Search PageLangsame Leistung MySql Query, Alternativen/Vorschläge?

Hier ist die Abfrage, wenn kein Filter ausgewählt:

SELECT 
    i.id_items AS id, 
    GROUP_CONCAT(DISTINCT iant.translation ORDER BY iant.translation asc SEPARATOR ', ') AS names, 
    GROUP_CONCAT(DISTINCT iafv.face_value ORDER BY iafv.face_value ASC SEPARATOR ', ') AS facesValues, 
    GROUP_CONCAT(DISTINCT iacut.translation ORDER BY iacut.translation ASC SEPARATOR ', ') AS currencies, 
    GROUP_CONCAT(DISTINCT cout.translation ORDER BY cout.translation ASC SEPARATOR ', ') AS countries, 
    GROUP_CONCAT(DISTINCT iacot.translation ORDER BY iacot.translation ASC SEPARATOR ', ') AS compositions, 
    GROUP_CONCAT(DISTINCT iacc.catalog_code ORDER BY iacc.catalog_code ASC SEPARATOR ', ') AS catalogCodes, 
    GROUP_CONCAT(DISTINCT iaio.issues_on ORDER BY iaio.issues_on ASC SEPARATOR ', ') AS issuesOn, 
    GROUP_CONCAT(DISTINCT iali.last_issues ORDER BY iali.last_issues ASC SEPARATOR ', ') AS latestIssues, 
    MIN(ucfs.price) AS minPrice, 
    SUM(ucfs.units) AS totalUnits  
FROM 
    items i 
INNER JOIN languages AS l 
    ON l.language_code = "en" 

LEFT JOIN items_atr_faces_values_match AS iafvm 
    ON iafvm.id_items = i.id_items 
LEFT JOIN items_atr_faces_values AS iafv 
    ON iafv.id_items_atr_faces_values = iafvm.id_items_atr_faces_values 


LEFT JOIN items_atr_currencies_match AS iacum 
    ON iacum.id_items = i.id_items 
LEFT JOIN items_atr_currencies_translations AS iacut 
    ON iacut.id_items_atr_currencies = iacum.id_items_atr_currencies 
    AND iacut.id_language_code = l.id_languages 
LEFT JOIN items_atr_currencies AS iacu 
    ON iacu.id_items_atr_currencies = iacum.id_items_atr_currencies 


LEFT JOIN items_atr_countries_match AS iacoum 
    ON iacoum.id_items = i.id_items 
LEFT JOIN items_atr_countries_translations AS cout 
    ON cout.id_items_atr_countries = iacoum.id_items_atr_countries 
    AND cout.id_language_code = l.id_languages 
LEFT JOIN items_atr_countries AS cou 
    ON cou.id_items_atr_countries = iacoum.id_items_atr_countries 


LEFT JOIN items_atr_compositions_match AS iacom 
    ON iacom.id_items = i.id_items 
LEFT JOIN items_atr_compositions_translations AS iacot 
    ON iacot.id_items_atr_compositions = iacom.id_items_atr_compositions 
    AND iacot.id_language_code = l.id_languages 
LEFT JOIN items_atr_compositions AS iaco 
    ON iaco.id_items_atr_compositions = iacom.id_items_atr_compositions 


LEFT JOIN items_atr_catalog_codes_match AS iaccm 
    ON iaccm.id_items = i.id_items 
LEFT JOIN items_atr_catalog_codes AS iacc 
    ON iacc.id_items_atr_catalog_codes = iaccm.id_items_atr_catalog_codes 


LEFT JOIN items_atr_issues_on_match AS iaiom 
    ON iaiom.id_items = i.id_items 
LEFT JOIN items_atr_issues_on AS iaio 
    ON iaio.id_items_atr_issues_on = iaiom.id_items_atr_issues_on 

LEFT JOIN items_atr_last_issues_match AS ialim 
    ON ialim.id_items = i.id_items 
LEFT JOIN items_atr_last_issues AS iali 
    ON iali.id_items_atr_last_issues = ialim.id_items_atr_last_issues 


LEFT JOIN items_atr_names_match AS ianm 
    ON ianm.id_items = i.id_items 
LEFT JOIN items_atr_names_translations AS iant 
    ON iant.id_items_atr_names = ianm.id_items_atr_names 
    AND iant.id_language_code = l.id_languages 
LEFT JOIN items_atr_names AS ian 
    ON ian.id_items_atr_names = ianm.id_items_atr_names   


LEFT JOIN users AS u On u.status = 'active' 
LEFT JOIN users_coins_for_sale AS ucfs 
    ON ucfs.id_users = u.id_users AND ucfs.id_items = i.id_items 



GROUP BY id 

ORDER BY 2 asc 

LIMIT 0, 20 

Hier ist die Erklärung:

Query Explanation

ich verwende Gruppe Concat da jedes Element eine oder mehr Übereinstimmungen mit den Attributen haben kann (Namen, Nominale, e tc).

Die Abfrage dauert 1,3 Sekunden, um mit 15k-Einträgen zu laufen. Die Tabellen werden bis zu 100.000 Einträge haben, so dass die Zeit zum Ausführen der Abfrage auch erhöht wird ...

Zuerst dachte ich, die Group_Concat war verantwortlich dafür, die Abfrage zu verlangsamen, aber dann, nach dem Entfernen der LIMIT 0, 20 Ich habe gesehen, dass es gleich lange dauert.

Ich habe versucht, die Grenze in einer Unterabfrage zu setzen:

... 
FROM 
    (SELECT id_items FROM items LIMIT 0, 20) AS i 
INNER JOIN languages AS l 
... 

Nun ist die Abfrage schnell ist, aber das Ergebnis ist nicht das, was ich erwartet hatte.

Haben Sie irgendwelche Vorschläge, diese Abfrage zu beheben?

Auch ich habe ein ähnliches Problem in dieser Abfrage, die Anzahl der Elemente zu zählen:

SELECT 
    COUNT(DISTINCT i.id_items) AS number 
FROM 
    items i 
INNER JOIN languages AS l 
    ON l.language_code = "en" 

LEFT JOIN items_atr_faces_values_match AS iafvm 
    ON iafvm.id_items = i.id_items 
LEFT JOIN items_atr_faces_values AS iafv 
    ON iafv.id_items_atr_faces_values = iafvm.id_items_atr_faces_values 


LEFT JOIN items_atr_currencies_match AS iacum 
    ON iacum.id_items = i.id_items 
LEFT JOIN items_atr_currencies_translations AS iacut 
    ON iacut.id_items_atr_currencies = iacum.id_items_atr_currencies 
    AND iacut.id_language_code = l.id_languages 
LEFT JOIN items_atr_currencies AS iacu 
    ON iacu.id_items_atr_currencies = iacum.id_items_atr_currencies 


LEFT JOIN items_atr_countries_match AS iacoum 
    ON iacoum.id_items = i.id_items 
LEFT JOIN items_atr_countries_translations AS cout 
    ON cout.id_items_atr_countries = iacoum.id_items_atr_countries 
    AND cout.id_language_code = l.id_languages 
LEFT JOIN items_atr_countries AS cou 
    ON cou.id_items_atr_countries = iacoum.id_items_atr_countries 


LEFT JOIN items_atr_compositions_match AS iacom 
    ON iacom.id_items = i.id_items 
LEFT JOIN items_atr_compositions_translations AS iacot 
    ON iacot.id_items_atr_compositions = iacom.id_items_atr_compositions 
    AND iacot.id_language_code = l.id_languages 
LEFT JOIN items_atr_compositions AS iaco 
    ON iaco.id_items_atr_compositions = iacom.id_items_atr_compositions 


LEFT JOIN items_atr_catalog_codes_match AS iaccm 
    ON iaccm.id_items = i.id_items 
LEFT JOIN items_atr_catalog_codes AS iacc 
    ON iacc.id_items_atr_catalog_codes = iaccm.id_items_atr_catalog_codes 


LEFT JOIN items_atr_issues_on_match AS iaiom 
    ON iaiom.id_items = i.id_items 
LEFT JOIN items_atr_issues_on AS iaio 
    ON iaio.id_items_atr_issues_on = iaiom.id_items_atr_issues_on 

LEFT JOIN items_atr_last_issues_match AS ialim 
    ON ialim.id_items = i.id_items 
LEFT JOIN items_atr_last_issues AS iali 
    ON iali.id_items_atr_last_issues = ialim.id_items_atr_last_issues 


LEFT JOIN items_atr_names_match AS ianm 
    ON ianm.id_items = i.id_items 
LEFT JOIN items_atr_names_translations AS iant 
    ON iant.id_items_atr_names = ianm.id_items_atr_names 
    AND iant.id_language_code = l.id_languages 
LEFT JOIN items_atr_names AS ian 
    ON ian.id_items_atr_names = ianm.id_items_atr_names   


LEFT JOIN users AS u On u.status = 'active' 
LEFT JOIN users_coins_for_sale AS ucfs 
    ON ucfs.id_users = u.id_users AND ucfs.id_items = i.id_items 

LIMIT 1 

Das dauert 0,8 Sekunden.

Erläuterung: Explanation

Ich betreibe die beiden Abfragen in meiner Suchseite (brauchen die zweite für die Paginierung), so dass es am Ende unter 2 Sekunden zu laden. Jetzt mit 15k Artikeln, also wenn ich 100k habe, dauert es viel länger.

Jeder Vorschlag wird zu schätzen wissen.

Vielen Dank im Voraus

Update: Dies ist die Erstellungsdaten:

CREATE TABLE IF NOT EXISTS `items` (
    `id_items` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_users` int(11) unsigned NOT NULL DEFAULT '0', 
    `date` date NOT NULL, 
    `views` bigint(20) NOT NULL DEFAULT '0', 
    `status` enum('draft','published') NOT NULL DEFAULT 'draft', 
    PRIMARY KEY (`id_items`), 
    UNIQUE KEY `id_items` (`id_items`), 
    KEY `id_users` (`id_users`), 
    CONSTRAINT `FK_items_users` FOREIGN KEY (`id_users`) REFERENCES `users` (`id_users`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Lista de items'; 

CREATE TABLE IF NOT EXISTS `items_atr_catalog_codes` (
    `id_items_atr_catalog_codes` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `catalog_code` varchar(100) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_catalog_codes`), 
    UNIQUE KEY `id_items_atr_catalog_codes` (`id_items_atr_catalog_codes`), 
    FULLTEXT KEY `catalog_code` (`catalog_code`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Los diferentes códigos de catálogo que tienen las monedas'; 


CREATE TABLE IF NOT EXISTS `items_atr_catalog_codes_match` (
    `id_items_atr_catalog_codes_match` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_catalog_codes` int(11) unsigned NOT NULL, 
    `id_items` int(11) unsigned NOT NULL, 
    PRIMARY KEY (`id_items_atr_catalog_codes_match`), 
    UNIQUE KEY `id_items_atr_catalog_codes_match` (`id_items_atr_catalog_codes_match`), 
    KEY `id_items` (`id_items`), 
    KEY `id_items_atr_catalog_codes` (`id_items_atr_catalog_codes`), 
    CONSTRAINT `FK_catalog_codes_items_match_catalog_codes` FOREIGN KEY (`id_items_atr_catalog_codes`) REFERENCES `items_atr_catalog_codes` (`id_items_atr_catalog_codes`), 
    CONSTRAINT `FK_catalog_codes_items_match_items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Asociación de monedas con los códigos del catálogo'; 


CREATE TABLE IF NOT EXISTS `items_atr_compositions` (
    `id_items_atr_compositions` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id_items_atr_compositions`), 
    UNIQUE KEY `id_items_atr_compositions` (`id_items_atr_compositions`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Lista de las diferentes composiciones'; 


CREATE TABLE IF NOT EXISTS `items_atr_compositions_match` (
    `id_items_atr_compositions_match` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_compositions` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_items` int(11) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_compositions_match`), 
    UNIQUE KEY `id_items_atr_compositions_match` (`id_items_atr_compositions_match`), 
    KEY `id_items` (`id_items`), 
    KEY `id_items_atr_compositions` (`id_items_atr_compositions`), 
    CONSTRAINT `FK_compositions_items_match_compositions` FOREIGN KEY (`id_items_atr_compositions`) REFERENCES `items_atr_compositions` (`id_items_atr_compositions`), 
    CONSTRAINT `FK_compositions_items_match_items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Las diferentes composiciones que puede tener un item'; 


CREATE TABLE IF NOT EXISTS `items_atr_compositions_translations` (
    `id_items_atr_compositions_translations` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_compositions` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_language_code` int(11) unsigned NOT NULL DEFAULT '0', 
    `translation` varchar(250) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_compositions_translations`), 
    UNIQUE KEY `id_items_atr_compositions_translations` (`id_items_atr_compositions_translations`), 
    KEY `id_language_code` (`id_language_code`), 
    KEY `id_items_atr_compositions` (`id_items_atr_compositions`), 
    FULLTEXT KEY `translation` (`translation`), 
    CONSTRAINT `FK_compositions_translations_compositions` FOREIGN KEY (`id_items_atr_compositions`) REFERENCES `items_atr_compositions` (`id_items_atr_compositions`), 
    CONSTRAINT `FK_compositions_translations_languages` FOREIGN KEY (`id_language_code`) REFERENCES `languages` (`id_languages`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Traducciones de las composiciones'; 

CREATE TABLE IF NOT EXISTS `items_atr_countries` (
    `id_items_atr_countries` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id_items_atr_countries`), 
    UNIQUE KEY `id_items_atr_countries` (`id_items_atr_countries`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 


CREATE TABLE IF NOT EXISTS `items_atr_countries_match` (
    `id_items_atr_countries_match` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_countries` int(11) unsigned NOT NULL, 
    `id_items` int(11) unsigned NOT NULL, 
    PRIMARY KEY (`id_items_atr_countries_match`), 
    UNIQUE KEY `items_atr_countries_match` (`id_items_atr_countries_match`), 
    KEY `id_items` (`id_items`), 
    KEY `id_items_atr_countries` (`id_items_atr_countries`), 
    CONSTRAINT `FK__countries` FOREIGN KEY (`id_items_atr_countries`) REFERENCES `items_atr_countries` (`id_items_atr_countries`), 
    CONSTRAINT `FK__items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='A que pais pertenece cada item'; 


CREATE TABLE IF NOT EXISTS `items_atr_countries_translations` (
    `id_items_atr_countries_translations` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_countries` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_language_code` int(11) unsigned NOT NULL DEFAULT '0', 
    `translation` varchar(250) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_countries_translations`), 
    UNIQUE KEY `id_items_atr_countries_translations` (`id_items_atr_countries_translations`), 
    KEY `id_items_atr_countries` (`id_items_atr_countries`), 
    KEY `id_language_code` (`id_language_code`), 
    FULLTEXT KEY `translation` (`translation`), 
    CONSTRAINT `FK__items_atr_countries` FOREIGN KEY (`id_items_atr_countries`) REFERENCES `items_atr_countries` (`id_items_atr_countries`), 
    CONSTRAINT `FK_items_atr_countries_translations_languages` FOREIGN KEY (`id_language_code`) REFERENCES `languages` (`id_languages`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 


CREATE TABLE IF NOT EXISTS `items_atr_currencies` (
    `id_items_atr_currencies` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id_items_atr_currencies`), 
    UNIQUE KEY `id_items_atr_currencies` (`id_items_atr_currencies`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Diferentes divisas de las monedas'; 


CREATE TABLE IF NOT EXISTS `items_atr_currencies_match` (
    `id_items_atr_currencies_match` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_currencies` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_items` int(11) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_currencies_match`), 
    UNIQUE KEY `id_items_atr_currencies_match` (`id_items_atr_currencies_match`), 
    KEY `id_items_atr_currencies` (`id_items_atr_currencies`), 
    KEY `id_items` (`id_items`), 
    CONSTRAINT `FK_items_atr_currencies_match_items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`), 
    CONSTRAINT `FK_items_atr_currencies_match_items_atr_currencies` FOREIGN KEY (`id_items_atr_currencies`) REFERENCES `items_atr_currencies` (`id_items_atr_currencies`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Asociación de las monedas con su divisa'; 


CREATE TABLE IF NOT EXISTS `items_atr_currencies_translations` (
    `id_items_atr_currencies_translations` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_currencies` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_language_code` int(11) unsigned NOT NULL DEFAULT '0', 
    `translation` varchar(255) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_currencies_translations`), 
    UNIQUE KEY `id_items_atr_currencies_translations` (`id_items_atr_currencies_translations`), 
    KEY `id_items_atr_currencies` (`id_items_atr_currencies`), 
    KEY `id_language_code` (`id_language_code`), 
    FULLTEXT KEY `translation` (`translation`), 
    CONSTRAINT `FK_items_atr_currencies_translations_items_atr_currencies` FOREIGN KEY (`id_items_atr_currencies`) REFERENCES `items_atr_currencies` (`id_items_atr_currencies`), 
    CONSTRAINT `FK_items_atr_currencies_translations_languages` FOREIGN KEY (`id_language_code`) REFERENCES `languages` (`id_languages`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Traducciones de las divisas'; 


CREATE TABLE IF NOT EXISTS `items_atr_faces_values` (
    `id_items_atr_faces_values` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `face_value` decimal(8,2) unsigned NOT NULL DEFAULT '0.00', 
    PRIMARY KEY (`id_items_atr_faces_values`), 
    UNIQUE KEY `id_items_atr_faces_values` (`id_items_atr_faces_values`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Valores faciales de las monedas'; 


CREATE TABLE IF NOT EXISTS `items_atr_faces_values_match` (
    `id_items_atr_faces_values_match` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_faces_values` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_items` int(11) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_faces_values_match`), 
    UNIQUE KEY `id_items_atr_faces_values_match` (`id_items_atr_faces_values_match`), 
    KEY `id_items_atr_faces_values` (`id_items_atr_faces_values`), 
    KEY `id_items` (`id_items`), 
    CONSTRAINT `FK_items_atr_faces_values_match_items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`), 
    CONSTRAINT `FK_items_atr_faces_values_match_items_atr_faces_values` FOREIGN KEY (`id_items_atr_faces_values`) REFERENCES `items_atr_faces_values` (`id_items_atr_faces_values`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Asociación de las monedas con sus valores faciales'; 


CREATE TABLE IF NOT EXISTS `items_atr_issues_on` (
    `id_items_atr_issues_on` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `issues_on` varchar(6) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_issues_on`), 
    UNIQUE KEY `id_items_atr_issues_on` (`id_items_atr_issues_on`), 
    FULLTEXT KEY `issues_on` (`issues_on`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Fecha en la que se emitió por primera vez la moneda'; 


CREATE TABLE IF NOT EXISTS `items_atr_issues_on_match` (
    `id_items_atr_issues_on_match` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_issues_on` int(11) unsigned NOT NULL, 
    `id_items` int(11) unsigned NOT NULL, 
    PRIMARY KEY (`id_items_atr_issues_on_match`), 
    UNIQUE KEY `id_items_atr_issues_on_match` (`id_items_atr_issues_on_match`), 
    KEY `id_items_atr_issues_on` (`id_items_atr_issues_on`), 
    KEY `id_items` (`id_items`), 
    CONSTRAINT `FK_items_atr_issues_on_match_items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`), 
    CONSTRAINT `FK_items_atr_issues_on_match_items_atr_issues_on` FOREIGN KEY (`id_items_atr_issues_on`) REFERENCES `items_atr_issues_on` (`id_items_atr_issues_on`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Asociaciones de emisiones con las monedas'; 


CREATE TABLE IF NOT EXISTS `items_atr_last_issues` (
    `id_items_atr_last_issues` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `last_issues` varchar(6) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_last_issues`), 
    UNIQUE KEY `id_items_atr_last_issues` (`id_items_atr_last_issues`), 
    FULLTEXT KEY `last_issues` (`last_issues`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Atributo de última emisión de la moneda'; 


CREATE TABLE IF NOT EXISTS `items_atr_last_issues_match` (
    `id_items_atr_last_issues_match` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_last_issues` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_items` int(11) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_last_issues_match`), 
    UNIQUE KEY `id_items_atr_last_issues_match` (`id_items_atr_last_issues_match`), 
    KEY `id_items_atr_last_issues` (`id_items_atr_last_issues`), 
    KEY `id_items` (`id_items`), 
    CONSTRAINT `FK_items_atr_last_issues_match_items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`), 
    CONSTRAINT `FK_items_atr_last_issues_match_items_atr_last_issues` FOREIGN KEY (`id_items_atr_last_issues`) REFERENCES `items_atr_last_issues` (`id_items_atr_last_issues`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Asociaciones entre las últimas emisiones y las monedas'; 


CREATE TABLE IF NOT EXISTS `items_atr_names` (
    `id_items_atr_names` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id_items_atr_names`), 
    UNIQUE KEY `id_items_atr_names` (`id_items_atr_names`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Contiene el atributo nombre de los items'; 


CREATE TABLE IF NOT EXISTS `items_atr_names_match` (
    `id_items_atr_names_match` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_names` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_items` int(11) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_names_match`), 
    UNIQUE KEY `id_items_atr_names_match` (`id_items_atr_names_match`), 
    KEY `id_items_atr_names` (`id_items_atr_names`), 
    KEY `id_items` (`id_items`), 
    CONSTRAINT `FK_items_atr_names_match_items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`), 
    CONSTRAINT `FK_items_atr_names_match_items_atr_names` FOREIGN KEY (`id_items_atr_names`) REFERENCES `items_atr_names` (`id_items_atr_names`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Asociación del atributo nombre con las monedas'; 


CREATE TABLE IF NOT EXISTS `items_atr_names_translations` (
    `id_items_atr_names_translations` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items_atr_names` int(11) unsigned NOT NULL DEFAULT '0', 
    `id_language_code` int(11) unsigned NOT NULL DEFAULT '0', 
    `translation` varchar(250) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id_items_atr_names_translations`), 
    UNIQUE KEY `id_items_atr_names_translations` (`id_items_atr_names_translations`), 
    KEY `id_language_code` (`id_language_code`), 
    KEY `id_items_atr_names` (`id_items_atr_names`), 
    KEY `STR_LEVE_idx` (`translation`), 
    FULLTEXT KEY `translation` (`translation`), 
    CONSTRAINT `FK_items_atr_names_translations_items_atr_names` FOREIGN KEY (`id_items_atr_names`) REFERENCES `items_atr_names` (`id_items_atr_names`), 
    CONSTRAINT `FK_items_atr_names_translations_languages` FOREIGN KEY (`id_language_code`) REFERENCES `languages` (`id_languages`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Traducciones del atributo nombre'; 


CREATE TABLE IF NOT EXISTS `users` (
    `id_users` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_languages` int(11) unsigned NOT NULL, 
    `password` char(128) NOT NULL, 
    `user_name` char(128) NOT NULL, 
    `last_login` datetime DEFAULT NULL, 
    `ip_register` varbinary(16) DEFAULT NULL, 
    `ip_last_login` varbinary(16) DEFAULT NULL, 
    `creation_date` datetime DEFAULT NULL, 
    `email` varchar(254) DEFAULT NULL, 
    `fb_user_id` varchar(255) DEFAULT NULL, 
    `fb_access_token` varchar(255) DEFAULT NULL, 
    `regen_password` varchar(254) DEFAULT NULL, 
    `activation_token` varchar(254) DEFAULT NULL, 
    `affiliated` varchar(30) NOT NULL DEFAULT 'no', 
    `credit` decimal(10,2) NOT NULL DEFAULT '0.00', 
    `status` enum('inactive','active','vacation','deleted') NOT NULL DEFAULT 'inactive', 
    `news` tinyint(1) NOT NULL DEFAULT '1', 
    `promotions` tinyint(1) NOT NULL DEFAULT '1', 
    PRIMARY KEY (`id_users`), 
    UNIQUE KEY `email` (`email`), 
    KEY `id_languages` (`id_languages`), 
    FULLTEXT KEY `fb_user_id` (`fb_user_id`), 
    FULLTEXT KEY `email2` (`email`), 
    FULLTEXT KEY `user_name` (`user_name`), 
    CONSTRAINT `FK_users_languages` FOREIGN KEY (`id_languages`) REFERENCES `languages` (`id_languages`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Lista de usuarios en la web'; 


CREATE TABLE IF NOT EXISTS `users_coins_for_sale` (
    `id_users_coins_for_sale` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `id_items` int(11) unsigned NOT NULL, 
    `id_users` int(11) unsigned NOT NULL, 
    `units` int(5) unsigned NOT NULL, 
    `year` varchar(5) NOT NULL, 
    `grade` enum('good','very_good','fine','very_fine','extra_fine','about_uncirculated','uncirculated','brilliant_uncirculated','proof') NOT NULL, 
    `price` decimal(8,2) unsigned NOT NULL, 
    `picture` varchar(500) DEFAULT NULL, 
    `comment` varchar(500) DEFAULT NULL, 
    `date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id_users_coins_for_sale`), 
    UNIQUE KEY `id_users_coins_for_sale_unique` (`id_users_coins_for_sale`), 
    KEY `id_items` (`id_items`), 
    KEY `id_users` (`id_users`), 
    KEY `year` (`year`), 
    KEY `grade` (`grade`), 
    KEY `id_users_coins_for_sale` (`id_users_coins_for_sale`), 
    CONSTRAINT `FK_users_coins_for_sale_items` FOREIGN KEY (`id_items`) REFERENCES `items` (`id_items`), 
    CONSTRAINT `FK_users_coins_for_sale_users` FOREIGN KEY (`id_users`) REFERENCES `users` (`id_users`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
+0

Haben Sie von der Verwendung von Indizes zur Beschleunigung von Joins gehört? Außerdem sieht Ihr Schema ziemlich groß aus. Mit wie vielen Aufzeichnungen beschäftigst du dich hier? –

+0

Das zweite Problem ist interessanter. Beachten Sie, dass Fragen zur Leistung IMMER CREATE TABLE-Anweisungen für ALLE relevanten Tabellen sowie die Ergebnisse von EXPLAIN erfordern. – Strawberry

+0

@Strawberry Ich aktualisierte die Antwort mit der Datenerstellung, um das Datenmodell zu sehen –

Antwort

1

Sie haben eine sehr komplizierte Abfrage, weil alle Produkte cartesianischen durchgeführt wird. Es ist ein bisschen schwer zu folgen, weil Sie kein Datenmodell bereitstellen.

Der Schlüssel zur Verbesserung der Leistung ist die Aggregation vor Beitritt, so dass Sie nicht die kartesischen Produkte erhalten. Es gibt zwei Möglichkeiten, dies zu tun. Eine besteht darin, Tabellen in der FROM-Klausel vorab zu aggregieren. Die andere besteht darin, korrelierte Unterabfragen zu verwenden. Wenn Sie die Zeilen weiter filtern (z. B. um 20 Zeilen zu erhalten), sind korrelierte Unterabfragen normalerweise die bessere Wahl.

Sie können es vereinfachen, indem Sie Unterabfragen verwenden, um die Aggregationen vor die Joins durchzuführen.Um ein Beispiel für die Aggregation nehmen:

SELECT i.id_items AS id, 
     (SELECT GROUP_CONCAT(iafv.face_value SEPARATOR ', ') 
     FROM tems_atr_faces_values_match iafvm JOIN 
      items_atr_faces_values iafv 
      ON iafv.id_items_atr_faces_values = iafvm.id_items_atr_faces_values AND 
       iafvm.id_items = i.id_items 
     ) as facesValues 
     . . . 
FROM items i INNER JOIN 
    languages AS l 
    ON l.language_code = 'en'; 

Für diese Abfrage möchten Sie dann Indizes auf items_atr_faces_values_match(id_items, id_items_atr_faces_values) und items_atr_faces_values(id_items_atr_faces_values, face_value.

Sie müssen dies für alle Ihre Beziehungen wiederholen.

+0

Ich aktualisierte die Antwort mit der Datenerstellung, um das Datenmodell mit dem Index zu sehen, den ich habe. Ich werde versuchen, Ihren Vorschlag jetzt zu tun –

+0

Ich habe gerade versucht, wie Sie vorgeschlagen [Link] (https://pastebin.com/4Pu6se8f), aber es dauert die gleiche Zeit zu laufen, vielleicht 100 ms weniger –

+0

@ NicolásGonzález. . . Die Unterabfragen sollten alle innere Verknüpfungen sein und die Indizes sind wichtig. –

0

fand ich die Lösung, in 0,125/0,180 Sekunden immer die Ergebnisse

Der Trick ist, eine Unterabfrage zuerst mit dem Attribut, das Sie bestellen, indem Sie und die ausgewählte Paginierung ausführen soll, dann das Produkt-ID in der Verwendung Rest von Joins.

Beispiel, Namen wie das Attribut der Auswahl auf Bestellung von:

SELECT 
    i.id_items AS id, 
    GROUP_CONCAT(DISTINCT iant.translation ORDER BY iant.translation asc SEPARATOR ', ') AS names, 
    GROUP_CONCAT(DISTINCT iafv.face_value ORDER BY iafv.face_value ASC SEPARATOR ', ') AS facesValues, 
    GROUP_CONCAT(DISTINCT iacut.translation ORDER BY iacut.translation ASC SEPARATOR ', ') AS currencies, 
    GROUP_CONCAT(DISTINCT cout.translation ORDER BY cout.translation ASC SEPARATOR ', ') AS countries, 
    GROUP_CONCAT(DISTINCT iacot.translation ORDER BY iacot.translation ASC SEPARATOR ', ') AS compositions, 
    GROUP_CONCAT(DISTINCT iacc.catalog_code ORDER BY iacc.catalog_code ASC SEPARATOR ', ') AS catalogCodes, 
    GROUP_CONCAT(DISTINCT iaio.issues_on ORDER BY iaio.issues_on ASC SEPARATOR ', ') AS issuesOn, 
    GROUP_CONCAT(DISTINCT iali.last_issues ORDER BY iali.last_issues ASC SEPARATOR ', ') AS latestIssues, 
    MIN(ucfs.price) AS minPrice, 
    SUM(ucfs.units) AS totalUnits 
FROM 
    (SELECT 
     i.id_items, 
     GROUP_CONCAT(DISTINCT iant.translation ORDER BY iant.translation asc SEPARATOR ', ') AS names 
    FROM 
     items i 
    INNER JOIN languages AS l ON l.language_code = "en" 

    LEFT JOIN items_atr_names_match AS ianm ON ianm.id_items = i.id_items 
    LEFT JOIN items_atr_names_translations AS iant ON iant.id_items_atr_names = ianm.id_items_atr_names 
     AND iant.id_language_code = l.id_languages 
    LEFT JOIN items_atr_names AS ian ON ian.id_items_atr_names = ianm.id_items_atr_names   

    GROUP BY id_items 

    ORDER BY 2 asc 

    LIMIT 0, 20) AS i 
INNER JOIN languages AS l ON l.language_code = "en" 

LEFT JOIN items_atr_faces_values_match AS iafvm ON iafvm.id_items = i.id_items 
LEFT JOIN items_atr_faces_values AS iafv ON iafv.id_items_atr_faces_values = iafvm.id_items_atr_faces_values 

LEFT JOIN items_atr_currencies_match AS iacum ON iacum.id_items = i.id_items 
LEFT JOIN items_atr_currencies_translations AS iacut ON iacut.id_items_atr_currencies = iacum.id_items_atr_currencies AND iacut.id_language_code = l.id_languages 
LEFT JOIN items_atr_currencies AS iacu ON iacu.id_items_atr_currencies = iacum.id_items_atr_currencies 


LEFT JOIN items_atr_countries_match AS iacoum ON iacoum.id_items = i.id_items 
LEFT JOIN items_atr_countries_translations AS cout ON cout.id_items_atr_countries = iacoum.id_items_atr_countries AND cout.id_language_code = l.id_languages 
LEFT JOIN items_atr_countries AS cou ON cou.id_items_atr_countries = iacoum.id_items_atr_countries 



LEFT JOIN items_atr_compositions_match AS iacom ON iacom.id_items = i.id_items 
LEFT JOIN items_atr_compositions_translations AS iacot ON iacot.id_items_atr_compositions = iacom.id_items_atr_compositions AND iacot.id_language_code = l.id_languages 
LEFT JOIN items_atr_compositions AS iaco ON iaco.id_items_atr_compositions = iacom.id_items_atr_compositions 



LEFT JOIN items_atr_catalog_codes_match AS iaccm ON iaccm.id_items = i.id_items 
LEFT JOIN items_atr_catalog_codes AS iacc ON iacc.id_items_atr_catalog_codes = iaccm.id_items_atr_catalog_codes 


LEFT JOIN items_atr_issues_on_match AS iaiom ON iaiom.id_items = i.id_items 
LEFT JOIN items_atr_issues_on AS iaio ON iaio.id_items_atr_issues_on = iaiom.id_items_atr_issues_on 


LEFT JOIN items_atr_last_issues_match AS ialim ON ialim.id_items = i.id_items 
LEFT JOIN items_atr_last_issues AS iali ON iali.id_items_atr_last_issues = ialim.id_items_atr_last_issues 


LEFT JOIN items_atr_names_match AS ianm ON ianm.id_items = i.id_items 
LEFT JOIN items_atr_names_translations AS iant ON iant.id_items_atr_names = ianm.id_items_atr_names AND iant.id_language_code = l.id_languages 
LEFT JOIN items_atr_names AS ian ON ian.id_items_atr_names = ianm.id_items_atr_names   

LEFT JOIN users AS u On u.status = 'active' 
LEFT JOIN users_coins_for_sale AS ucfs ON ucfs.id_users = u.id_users AND ucfs.id_items = i.id_items 


GROUP BY id 

ORDER BY 2 asc 

Ich hoffe, dass diese Antwort anderes Mal jemand rettet.

Frieden

1

Zu viele Tabellen.

nicht „normalisieren“ einfache Dinge wie face_value und issues_on (und wahrscheinlich auch andere. Es führt zu zusätzlichen JOINs ohne zusätzliche Flexibilität usw.

ich eine Land-ID zu sehen, aber kein Land Name ?? Es kann besser sein, diese statt der Tabelle zu verwenden und id.

country_code CHAR(2) CHARACTER SET ascii 

und den Standard-2-Buchstaben-Ländercodes verwenden (Es wird auch eine 4-Byte-INT mit einem 2-Byte-String in verschiedenen Tabellen ersetzen

Auch 10

, da ein PRIMARY KEY ist per Definition (in MySQL), UNIQUE:

PRIMARY KEY(x) 
UNIQUE  (x) -- DROP this 

Benötigen Sie LEFT? Das heißt, fehlt möglicherweise die Zeile in der "richtigen" Tabelle? Wenn nicht, entfernen Sie LEFT.

Nachdem Sie diese bereinigt haben, bitten Sie um eine weitere Überprüfung.

+0

Hi @ rick-james, danke für die Anregungen.Ich verwende country_codes in der Landtabelle für meine Benutzer, aber ich kann keine Ländercodes in der Tabelle items_atr_country verwenden, da die Elemente "nicht existierende" Länder wie "Römisches Reich" verwenden. Ich brauche Links Joins becase einige Elemente haben keine bestimmten Attribute (Land, Gesicht Wert, etc. könnte fehlen) und ich brauche einen Null-Verweis zu wissen, es gibt keine Übereinstimmung mit dem Attribut. Danke für den einzigartigen Tipp, ich werde sie loswerden. Ich schätze deine Rezension, ich bin kein db-Experte, ich lerne, wie ich gehe. –

+0

Ein möglicherweise fehlendes Attribut könnte beispielsweise 'face_value' decimal (8,2) unsigned NULL DEFAULT NULL sein, wodurch ein JOIN vermieden wird. (Es sei denn, es gibt weitere Informationen, die Sie nicht in der 'CREATE TABLE' angezeigt haben). –