mysql查询使用order by和group by更慢

knsnq2tg  于 2021-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(376)

在我的vps上,我试图执行一个查询,我必须在大约1800条记录中提取20个结果,查询由3个结果组成 INNER JOIN ,如果我不插入 GROUP BY id ORDER BY id DESC 在查询结束时,查询将在0.0143秒内执行,而如果插入 GROUP BY id ORDER BY id DESC 在查询结束时,执行需要3.1447秒,你能告诉我为什么吗?
以下是查询:

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


结构如下:
表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;

表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;

表prodotti\ U 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;

表类别:

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;

我试图运行相同的查询,在一个数据库克隆上(相同的数据)在另外两个服务器上是没有问题的,它只发生在我从我的vps运行它。
以下是我的配置:
数据库服务器
服务器:通过unix套接字的本地主机
服务器类型:mysql
服务器版本:5.7.22-0ubuntu0.16.04.1-(ubuntu)
协议版本:10
用户:root@localhost
服务器字符集:utf-8 unicode(utf8)
web服务器
apache/2.4.18(ubuntu)modïfcgid/2.3.9 openssl/1.0.2g
数据库客户端版本:libmysql-mysqlnd 5.0.12-dev-20150407-$id:38fea24f2847fa7519001be390c98ae0acafe387$
php扩展:mysqlidocumentation curldocumentation mbstringdocumentation
php版本:7.2.5-1+ubuntu16.04.1+deb.sury.org+1
phpmyadmin:版本信息:4.6.6deb1+deb.cihar.com~xenial.2
非常感谢大家。
编辑
解释结果:

编辑2:
解释第二个数据库的结果:

70gysomp

70gysomp1#

对于你的问题,

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

您需要在用于联接表的字段上建立索引。在主键上有索引,但没有与之匹配的索引,因此数据库必须搜索联接表的每条记录。
将索引添加到 prodotti.sito , prodotti.categoria , prodotti_prezzi.prodotto 这将是一个与众不同的世界。你也可以在 attivo , forced ,和 regione 好的措施。
我怀疑你的索引在所有3台服务器上都不一样,而速度慢的那台缺少索引。
fwiw,还有几个注意事项:
在普罗多蒂身上, unique key id 是多余的; 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' ) 更容易表达为 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')

相关问题