[英]Mysql query with inner join more slow with Order by and Group By
on my vps I'm trying to execute a query, I have to extract 20 results in about 1800 records, the query is formed by 3 INNER JOIN
, if I execute it without inserting the GROUP BY id ORDER BY id DESC
at the end of the query query is executed in 0.0143 seconds, while if I insert the GROUP BY id ORDER BY id DESC
at the end of the query, it takes 3.1447 seconds the execution, can you tell me why? 在我的vps上,我试图执行查询,我必须在大约1800条记录中提取20个结果,该查询是由3个
INNER JOIN
,如果我执行该查询时未在末尾插入GROUP BY id ORDER BY id DESC
查询查询将在0.0143秒内执行,而如果我在查询末尾插入GROUP BY id ORDER BY id DESC
,则需要3.1447秒的执行时间,你能告诉我为什么吗?
This is the query: 这是查询:
SELECT s.nome,s.url as urlSito,s.importospedizione,p.titolo,p.descrizione,p.prezzo,p.img,p.annata,p.formato,p.denominazione,p.regione,c.categoria,c.url,s.id AS sito,p.id AS prodotto,pp.prezzo AS old,pp.data,p.sku
FROM prodotti AS p
INNER JOIN siti AS s ON p.sito = s.id
INNER JOIN categorie AS c ON p.categoria = c.id
INNER JOIN prodotti_prezzi AS pp ON p.id = pp.prodotto
WHERE p.attivo = 1 AND s.attivo = 1 AND p.forced = 0 AND
( p.regione = 'Valle d\'Aosta' OR p.regione = 'Piemonte' OR p.regione = 'Liguria' OR 'Lombardia' OR p.regione = 'Trentino-Alto Adige' OR p.regione = 'Veneto' OR p.regione = 'Friuli-Venezia Giulia' OR p.regione = 'Emilia-Romagna' OR p.regione = 'Toscana' OR p.regione = 'Umbria' OR p.regione = 'Lazio' OR p.regione = 'Marche' OR p.regione = 'Abruzzo' OR p.regione = 'Molise' OR p.regione = 'Campania' OR p.regione = 'Puglia' OR p.regione = 'Basilicata' OR p.regione = 'Calabria' OR p.regione = 'Sardegna' OR p.regione = 'Sicilia' )
GROUP BY p.id
ORDER BY p.prezzo ASC
LIMIT 0,20
This is the structure: 结构如下:
Table prodotti: 表prodotti:
CREATE TABLE `prodotti` ( `id` int(11) NOT NULL, `sku` text NOT NULL, `titolo` text NOT NULL, `descrizione` longtext NOT NULL, `sito` int(11) NOT NULL, `prezzo` double NOT NULL, `qta` int(11) NOT NULL, `url` text NOT NULL, `produttore` text NOT NULL, `regione` text NOT NULL, `denominazione` text NOT NULL, `annata` int(11) NOT NULL, `formato` text NOT NULL, `attivo` int(11) NOT NULL, `img` text NOT NULL, `home` int(11) NOT NULL, `categoria` int(11) NOT NULL, `consigli` int(11) NOT NULL, `forced` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `prodotti`
-- ALTER TABLE `prodotti` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `id` (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `prodotti`
-- ALTER TABLE `prodotti` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
Table siti: 表siti:
CREATE TABLE `siti` (
`id` int(11) NOT NULL,
`nome` text NOT NULL,
`indirizzo` text NOT NULL,
`tel` text NOT NULL,
`pagamento` text NOT NULL,
`spedizione` text NOT NULL,
`url` text NOT NULL,
`email` text NOT NULL,
`password` varchar(40) NOT NULL,
`emailweb` text NOT NULL,
`zone` text NOT NULL,
`data` int(11) NOT NULL,
`aggiornamento` int(11) NOT NULL,
`urlaggiornamento` text NOT NULL,
`img` text NOT NULL,
`click` double NOT NULL,
`max` double NOT NULL,
`ultimo` int(11) NOT NULL,
`attivo` int(11) NOT NULL,
`importospedizione` double NOT NULL,
`descrizione` longtext NOT NULL,
`web` text NOT NULL,
`iva` text NOT NULL,
`sociale` text NOT NULL,
`avviso` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `siti`
--
ALTER TABLE `siti`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `siti`
--
ALTER TABLE `siti`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
Table prodotti_prezzi: 表prodotti_prezzi:
CREATE TABLE `prodotti_prezzi` (
`id` int(11) NOT NULL,
`prodotto` int(11) NOT NULL,
`prezzo` double NOT NULL,
`data` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `prodotti_prezzi`
--
ALTER TABLE `prodotti_prezzi`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `prodotti_prezzi`
--
ALTER TABLE `prodotti_prezzi`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
Table categorie: 表类别:
CREATE TABLE `categorie` (
`id` int(11) NOT NULL,
`categoria` text NOT NULL,
`url` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `categorie`
--
ALTER TABLE `categorie`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `categorie`
--
ALTER TABLE `categorie`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
I tried to run the same query, on a database clone (same data) on two other servers is the problem does not occur, it only happens when I run it from my vps. 我尝试在其他两台服务器上的数据库克隆(相同数据)上运行相同的查询,是不会发生问题,仅当我从vps运行它时才会发生。
Here is my configuration: 这是我的配置:
Database server 数据库服务器
Web server 网络服务器
phpMyAdmin: Version information: 4.6.6deb1+deb.cihar.com~xenial.2 phpMyAdmin:版本信息:4.6.6deb1 + deb.cihar.com〜xenial.2
Thanks a lot to everyone. 非常感谢大家。
EDIT 编辑
EXPLAIN result: 说明结果:
EDIT 2: 编辑2:
EXPLAIN result on second database: 在第二个数据库上解释结果:
For your query, 对于您的查询,
SELECT s.nome,s.url as urlSito,s.importospedizione,p.titolo,p.descrizione,p.prezzo,p.img,p.annata,p.formato,p.denominazione,p.regione,c.categoria,c.url,s.id AS sito,p.id AS prodotto,pp.prezzo AS old,pp.data,p.sku
FROM prodotti AS p
INNER JOIN siti AS s ON p.sito = s.id
INNER JOIN categorie AS c ON p.categoria = c.id
INNER JOIN prodotti_prezzi AS pp ON p.id = pp.prodotto
WHERE p.attivo = 1 AND s.attivo = 1 AND p.forced = 0 AND
( p.regione = 'Valle d\'Aosta' OR p.regione = 'Piemonte' OR p.regione = 'Liguria' OR 'Lombardia' OR p.regione = 'Trentino-Alto Adige' OR p.regione = 'Veneto' OR p.regione = 'Friuli-Venezia Giulia' OR p.regione = 'Emilia-Romagna' OR p.regione = 'Toscana' OR p.regione = 'Umbria' OR p.regione = 'Lazio' OR p.regione = 'Marche' OR p.regione = 'Abruzzo' OR p.regione = 'Molise' OR p.regione = 'Campania' OR p.regione = 'Puglia' OR p.regione = 'Basilicata' OR p.regione = 'Calabria' OR p.regione = 'Sardegna' OR p.regione = 'Sicilia' )
GROUP BY p.id
ORDER BY p.prezzo ASC
LIMIT 0,20
you need to have indexes on the fields used to join the tables. 您需要在用于联接表的字段上具有索引。 You have indexes on the primary keys, but nothing to match them with, so the database has to search through every record of the joined tables.
您在主键上有索引,但是没有与之匹配的索引,因此数据库必须搜索联接表的每个记录。
Add indexes to prodotti.sito
, prodotti.categoria
, prodotti_prezzi.prodotto
and that should make a world of difference. 将索引添加到
prodotti.sito
, prodotti.categoria
, prodotti_prezzi.prodotto
,这应该会有所作为。 You could also throw in indexes on attivo
, forced
, and regione
for good measure. 您也可以在
attivo
, forced
和regione
上attivo
索引,以提高性能。
My suspicion is that your indexes are not the same on all 3 servers, and the slow one is lacking the indexes. 我怀疑您的索引在所有3台服务器上都不相同,而慢速的索引却缺少索引。
FWIW, a couple of other notes: FWIW,其他一些注意事项:
On prodotti, unique key id
is superfluous; 在prodotti上,
unique key id
是多余的; primary key
is by definition unique 根据定义,
primary key
是唯一的
p.regione = 'Valle d\\'Aosta' OR p.regione = 'Piemonte' OR p.regione = 'Liguria' OR 'Lombardia' OR p.regione = 'Trentino-Alto Adige' OR p.regione = 'Veneto' OR p.regione = 'Friuli-Venezia Giulia' OR p.regione = 'Emilia-Romagna' OR p.regione = 'Toscana' OR p.regione = 'Umbria' OR p.regione = 'Lazio' OR p.regione = 'Marche' OR p.regione = 'Abruzzo' OR p.regione = 'Molise' OR p.regione = 'Campania' OR p.regione = 'Puglia' OR p.regione = 'Basilicata' OR p.regione = 'Calabria' OR p.regione = 'Sardegna' OR p.regione = 'Sicilia' )
can be more easily expressed as 可以更容易地表示为
p.regione IN('Valle d\\'Aosta','Piemonte','Liguria','Lombardia','Trentino-Alto Adige','Veneto','Friuli-Venezia Giulia','Emilia-Romagna','Toscana','Umbria','Lazio','Marche','Abruzzo','Molise','Campania','Puglia','Basilicata','Calabria','Sardegna','Sicilia')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.