Autor | Zpráva | ||
---|---|---|---|
ales_naprstek Profil |
#1 · Zasláno: 30. 8. 2020, 18:13:05
Prosím o radu s pomalým SQL dotazem, jedná se o výběr produktů z eshopu. Bohužel se databáze rozrostla a eshop obsahuje trošku více produktů. Zkoušel jsem několik úprav, ale žádná mne nedovedla ke zlepšení času. Dotaz, počty záznamů a strukturu tabulek uvádím pod problémovým selectem.
Předem velmi děkuji za jakoukoliv pomoc. # Query_time: 6.127047 Lock_time: 0.000253 Rows_sent: 15 Rows_examined: 1123184 SET timestamp=1598802021; SELECT p.id_produkt FROM t_e_produkty AS p INNER JOIN (SELECT DISTINCT kp.id_produkt FROM t_e_vazba_katprod AS kp INNER JOIN t_e_kategorie AS k ON kp.id_e_kategorie = k.id_e_kategorie WHERE k.lft >= 1 AND k.rft <= 2022) t ON p.id_produkt = t.id_produkt WHERE p.zobrazovat = 'A' AND p.platny = 'A' ORDER BY p.d_zobrazovat_od DESC LIMIT 0, 15; Tabulka t_e_produkty obsahuje 281 934 řádků. Tabulka t_e_kategorie obsahuje 1 504 řádků. A vazební tabulka t_e_vazba_katprod obsahuje 296 702 řádků. Struktura je následující: CREATE TABLE `t_e_kategorie` ( `id_e_kategorie` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `nazev_cz` varchar(80) CHARACTER SET utf8 DEFAULT NULL, `popis_cz` varchar(255) CHARACTER SET utf8 DEFAULT NULL, `nazev_en` varchar(80) CHARACTER SET utf8 DEFAULT NULL, `popis_en` varchar(255) CHARACTER SET utf8 DEFAULT NULL, `nazev_de` varchar(80) CHARACTER SET utf8 DEFAULT NULL, `popis_de` varchar(255) CHARACTER SET utf8 DEFAULT NULL, `id_e_kat_rodic` smallint(5) unsigned NOT NULL DEFAULT '0', `poradi` tinyint(3) unsigned NOT NULL DEFAULT '0', `lft` smallint(5) unsigned NOT NULL DEFAULT '0', `rft` smallint(5) unsigned NOT NULL DEFAULT '0', `pocet_polozek` int(10) NOT NULL DEFAULT '0', `pocet_akci` int(10) NOT NULL DEFAULT '0', `pocet_doporucujeme` int(10) DEFAULT '0', `cesta_gen_cz` text CHARACTER SET utf8, `cesta_gen_en` text CHARACTER SET utf8, `cesta_gen_de` text CHARACTER SET utf8, `platny` enum('A','N') CHARACTER SET utf8 NOT NULL DEFAULT 'A', PRIMARY KEY (`id_e_kategorie`), KEY `idx_lft` (`lft`), KEY `idx_rft` (`rft`), KEY `idx_id_e_kat_rodic` (`id_e_kat_rodic`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci; CREATE TABLE `t_e_produkty` ( `id_produkt` int(10) unsigned NOT NULL AUTO_INCREMENT, `id_kvalita` tinyint(3) unsigned DEFAULT NULL, `id_dodavatel` smallint(5) unsigned DEFAULT NULL, `d_vlozeni` datetime DEFAULT NULL, `d_zobrazovat_od` datetime DEFAULT NULL COMMENT 'od kdy se ma zobrazovat na hlavni strance', `pocet_obrazku` smallint(5) unsigned DEFAULT '0' COMMENT 'na tohle je trigger na t_obrazky', `provize` tinyint(3) unsigned DEFAULT NULL, `nazev_cz` varchar(255) DEFAULT NULL, `nazev_en` varchar(255) DEFAULT NULL, `nazev_de` varchar(255) DEFAULT NULL, `popis_cz` text, `popis_en` text, `popis_de` text, `hmotnost` smallint(5) unsigned DEFAULT NULL, `cena` int(10) DEFAULT NULL, `doporucujeme` enum('A','N') DEFAULT 'N', `d_doporucujeme` date DEFAULT NULL, `neprehlednete` enum('A','N') DEFAULT 'N', `akce` enum('A','N') DEFAULT 'N' COMMENT 'uz se nepouziva', `cena_akce` int(10) unsigned DEFAULT NULL COMMENT 'uz se nepouziva', `sleva_akce` tinyint(3) unsigned NOT NULL DEFAULT '0', `d_akce_od` date DEFAULT NULL, `d_akce_do` date DEFAULT NULL, `na_objednavku` enum('A','N') DEFAULT 'N', `pocet_skladem` smallint(5) unsigned DEFAULT '1', `prodano` enum('A','N') DEFAULT 'N' COMMENT 'nepouziva se a asi ani nebude', `dat_prodano` date DEFAULT NULL COMMENT 'nepouziva se a asi ani nebude', `vyuctovano` enum('A','N') DEFAULT 'N', `pocet_zobrazeni` int(11) NOT NULL DEFAULT '0', `zobrazovat` enum('A','N') NOT NULL DEFAULT 'A', `platny` enum('A','N') DEFAULT 'A' COMMENT 'pouziva se pro zkopirovane do akce', `vraceno` enum('A','N') DEFAULT 'N' COMMENT 'neprodano, vraceno dodavateli', `dt_vraceno` date DEFAULT NULL, PRIMARY KEY (`id_produkt`), KEY `idx_akce` (`akce`), KEY `idx_katalog` (`katalogove_cislo`), KEY `idx_cena` (`cena`), KEY `idx_doporucujeme` (`doporucujeme`), KEY `idx_nazev` (`nazev_cz`), KEY `id_dodavatel` (`id_dodavatel`), KEY `zobrazovat` (`zobrazovat`), KEY `idx_d_akce_od` (`d_akce_od`), KEY `idx_d_akce_do` (`d_akce_do`), KEY `idx_neprehlednete` (`neprehlednete`), KEY `idx_platny` (`platny`), KEY `idx_d_zobrazovat_od` (`d_zobrazovat_od`), KEY `zobrazovat_platny` (`zobrazovat`,`platny`), FULLTEXT KEY `idx_flt_nazev` (`nazev_cz`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE `t_e_vazba_katprod` ( `id_produkt` int(11) DEFAULT NULL, `id_e_kategorie` int(11) DEFAULT NULL, UNIQUE KEY `vazba` (`id_produkt`,`id_e_kategorie`), KEY `vazba2` (`id_e_kategorie`,`id_produkt`) ) ENGINE=MyISAM DEFAULT C |
||
Kajman Profil |
#2 · Zasláno: 30. 8. 2020, 23:18:45
Pro podmínku
k.lft >= 1 AND k.rft <= 2022 by se hodil r-tree index. V mysql tak fungují spatial indexy nad geometrickými daty.
explainextended.com/2009/09/29/adjacency-list-vs-nested-sets-mysql Případně u verzí mysql podporující rekurzi, zkusit pro omezení stromu použít ji. mariadb.com/kb/en/recursive-common-table-expressions-overview Dále bych zkusil pro porovnání rychlostí a explainů: - napsat dotaz i do jednoho joinu bez poddotazu - zapoznámkovat podmínky na p.zobrazovat a p.platny (pokud podmínku splňují skoro všechy řádky, někdy pomůže tyto podmínky dát v mysql do having části) |
||
Časová prodleva: 4 roky
|
0