MYSQL 查询慢 SELECT DISTINCT

Posted

技术标签:

【中文标题】MYSQL 查询慢 SELECT DISTINCT【英文标题】:MYSQL query slow SELECT DISTINCT 【发布时间】:2021-07-06 00:02:04 【问题描述】:

我想输出最近 3 天我的分类广告中最常用的搜索项

我有一个额外的表格,我在其中保存所有搜索项以及日期和一个计数器,如果再次使用搜索(以及将来使用它所使用的类别页面),计数器会增加

这可行,但速度低于预期。

关于如何提高性能的任何想法?

更新: 似乎复制到临时表会导致问题 - 我该如何更改?

SQL 看起来像:

SELECT distinct search_item 
FROM `tb_search` 
WHERE added >= ( CURDATE() - INTERVAL 3 DAY ) 
ORDER BY count DESC 
LIMIT 0,20

解释:

id select_type table        type    possible_keys  key     key_len ref rows Extra
1   SIMPLE     tb_search    range   added          added    3       NULL 4537   Using index condition; Using temporary; Using filesort...   

但是很慢,php脚本的完整40ms执行时间需要12ms所以25%

表结构(Innodb) 23.000 条记录

tb_search
Column  Type    Null    Default Links to    Comments    Media (MIME) type
id (Primary)    bigint(20)  No              
search_item varchar(30) No              
category    varchar(30) Yes NULL            
added   date    No              
count   smallint(6) No              


 Indexes
    Keyname Type    Unique  Packed  Column  Cardinality Collation   Null    Comment
    PRIMARY BTREE   Yes No  id  23744   A   No  
    search_item BTREE   No  No  search_item 11872   A   No  
    added   BTREE   No  No  added   44  A   No  

空间使用

数据 1.5 MiB 索引 1.9 MiB 开销 466.0 MiB

开销有问题吗?我怎样才能摆脱它?优化所有表并没有改变它。 db 总大小为 86MB

**Detailed profile**

1   Starting    48 µs
2   Checking Permissions    6 µs
3   Opening Tables  14 µs
4   After Opening Tables    13 µs
5   System Lock 5 µs
6   Table Lock  3 µs
7   After Table Lock    5 µs
8   Init    20 µs
9   Optimizing  11 µs
10  Statistics  85 µs
11  Preparing   34 µs
12  Executing   4 µs
13  Creating Tmp Table  24 µs
**14    Copying To Tmp Table    9.7 ms**
15  Sorting Result  218 µs
16  Sending Data    18 µs
17  End 4 µs
18  Removing Tmp Table  9 µs
19  End 5 µs
20  Query End   7 µs
21  Closing Tables  9 µs
22  Freeing Items   8 µs
23  Updating Status 21 µs
24  Cleaning Up 4 µs
Summary by stateDocumentation
State
Total Time
% Time
Calls
ø Time
Starting    48 µs   0.47%   1   48 µs
Checking Permissions    6 µs    0.06%   1   6 µs
Opening Tables  14 µs   0.14%   1   14 µs
After Opening Tables    13 µs   0.13%   1   13 µs
System Lock 5 µs    0.05%   1   5 µs
Table Lock  3 µs    0.03%   1   3 µs
After Table Lock    5 µs    0.05%   1   5 µs
Init    20 µs   0.19%   1   20 µs
Optimizing  11 µs   0.11%   1   11 µs
Statistics  85 µs   0.83%   1   85 µs
Preparing   34 µs   0.33%   1   34 µs
Executing   4 µs    0.04%   1   4 µs
Creating Tmp Table  24 µs   0.23%   1   24 µs
**Copying To Tmp Table  9.7 ms  94.42%  1   9.7 ms**
Sorting Result  218 µs  2.12%   1   218 µs
Sending Data    18 µs   0.17%   1   18 µs
End 4 µs    0.04%   2   2 µs
Removing Tmp Table  9 µs    0.09%   1   9 µs
Query End   7 µs    0.07%   1   7 µs
Closing Tables  9 µs    0.09%   1   9 µs
Freeing Items   8 µs    0.08%   1   8 µs
Updating Status 21 µs   0.20%   1   21 µs
Cleaning Up 4 µs    0.04%   1   4 µs

表结构

-- phpMyAdmin SQL Dump
-- version 5.0.3
-- https://www.phpmyadmin.net/
--
-- Host: localhost:3306
-- Generation Time: Apr 10, 2021 at 11:03 AM
-- Server version: 5.5.68-MariaDB
-- PHP Version: 7.3.27

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `terraristik_main`
--

-- --------------------------------------------------------

--
-- Table structure for table `tb_search`
--

CREATE TABLE `tb_search` (
  `id` bigint(20) UNSIGNED NOT NULL,
  `search_item` varchar(30) NOT NULL,
  `category` varchar(30) DEFAULT NULL,
  `added` date NOT NULL,
  `count` smallint(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `tb_search`
--
ALTER TABLE `tb_search`
  ADD PRIMARY KEY (`id`),
  ADD KEY `search_item` (`search_item`),
  ADD KEY `added` (`added`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `tb_search`
--
ALTER TABLE `tb_search`
  MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

【问题讨论】:

也许这与WHERE added >= ( CURDATE() - INTERVAL 3 DAY ) 23 000 条记录无关 你能告诉我们那个特定表的CREATE TABLE 输出吗? @Eljakim 在上面更新并包含完整的结构。但请查看速度配置文件 - 似乎复制到 tmp 表是问题。 @FlashThunder 我已经将其更改为 WHERE added >= 21-03-2021 并且没有任何改进。 【参考方案1】:

解决方案

通过为count 添加索引,我将时间缩短了 95% 以上!!! 现在整个操作大约需要 1-1.5 毫秒。

copy_to_temp table 从 10 毫秒减少到 0.5 毫秒 - 仍然使用 65% 的时间,但速度足以满足我的需求。

【讨论】:

【参考方案2】:

用于三天前的日期:

SELECT distinct search_item 
FROM `tb_search t` 
WHERE t.date >= DATE_ADD(CURDATE(), INTERVAL -3 DAY);

或者你可以使用:

SELECT distinct search_item 
FROM `tb_search t` 
WHERE t.date >= ( CURDATE() - INTERVAL 3 DAY );

【讨论】:

我需要20个最受欢迎的搜索项

以上是关于MYSQL 查询慢 SELECT DISTINCT的主要内容,如果未能解决你的问题,请参考以下文章

MySQL,在执行 SELECT DISTINCT 查询之前合并 2 个或更多表?

如何在 python 代码中添加 mysql 查询 select distinct?

mysql查询:SELECT DISTINCT column1,GROUP BY column2

php查询mysql时,报超出内存错误(select count(distinct))时

mysql 去除重复 Select中DISTINCT关键字的用法 在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留

MySQL查询关键字之select/where/group by/having/distinct/order by/limit/regexp/like