【问题标题】:Need an optimized mysql query需要优化的 mysql 查询
【发布时间】:2019-09-23 05:14:32
【问题描述】:

上面是我的mysql表。 dvr_id 列具有相同表主键 dealer_visit_id 的值,dvr_id 是可为空的列。 我需要获取dealer_visit 表的所有记录,这很简单。但问题是,与所有记录一起,我需要一个 "count"dvr_id 列,对应于要获取的每条记录。

例如:如果我想获取dealer_visit_id2660的记录,我将查询写成

select col1,col2,col3, (SELECT count(dvr_id) from dealer_visit  where dvr_id=dealer_visit_id GROUP BY dvr_id as totalDVRs) 
 from dealer_visit;

需要这样的东西,但是当我尝试获取 1000 多条记录时查询太慢了。获取记录需要 9 秒以上。当我删除 COUNT 查询时,它会在 1-1.5 秒内获取 1000 多条记录。

如何优化查询,以便根据 1 列值获取记录以及行数?

我希望我的问题很清楚。

编辑1:假设数据集如下:

现在如果我获取 dealer_visit_id 33 的记录,我应该得到 dealer_visit_id 33 ALONG WITH count(dvr_id) 具有 33 的行,如示例数据集 所以上述数据集的预期输出应该是:

dealer_visit_id = 33 的选择查询的预期输出(dvr_id 列的计数值为 33)

|   dealer_visit_id   |   employee_id   |   originally_created_by    |   dealer_id   |   COUNT(dvr_id) |
--------------------------------------------------------------------------------
|    33               |     20          |         20                 |      226      |    6            |

Count(dvr_id) = 6 在我试图快速获取的问题中很重要。您在此处看到,结果是dealer_visit_id=33 的行和可以称为其子行 或根据示例数据集为6 的相关行的计数。

下面是解释表的输出

Field                   Type                          Null    Key     Default  Extra           
----------------------  ----------------------------  ------  ------  -------  ----------------
dealer_visit_id         int(10) unsigned              NO      PRI     (NULL)   auto_increment  
employee_id             int(10) unsigned              NO              (NULL)                   
originally_created_by   int(10) unsigned              YES             (NULL)                   
dealer_id               int(10) unsigned              NO              (NULL)                   
dvr_id                  int(10) unsigned              YES             (NULL)                   
dealer_emo_id           bigint(10) unsigned           YES             (NULL)                   
department              enum('SALES','ASSURED','EM')  YES             (NULL)                   
dvr_type                enum('FOLLOWUP','DVR')        YES             (NULL)                   
present_members         varchar(4096)                 YES             (NULL)                   
visit_date              date                          NO              (NULL)                   
location                varchar(45)                   YES             (NULL)                   
overall_remarks         text                          YES             (NULL)                   
active                  tinyint(1)                    YES             1                        
is_complete             tinyint(1)                    YES             1                        
is_closed               tinyint(1)                    YES             (NULL)                   
is_data_migrated        tinyint(1)                    YES             0                        
report_close_date       datetime                      YES             (NULL)                   
report_completion_date  datetime                      YES             (NULL)                   
followup_number         int(11)                       YES             (NULL)                   
total_followups         int(11) unsigned              YES             0                        
last_modified_date      datetime                      YES             (NULL)                   
autosave_time           datetime                      YES             (NULL)                   
create_date             datetime                      NO              (NULL)                   
updated_by              int(10) unsigned              NO              (NULL)                   
nearest_visit_date      date                          YES             (NULL)                   

【问题讨论】:

  • count(dvr_id) group by dvr_id return always 1 ...尝试更好地解释添加清晰的数据样本和预期结果
  • 您不应使用子查询或联接来获取此类数据。请说明您使用的是什么技术,以便更容易以优化的方式获取数据
  • 我在我的问题中提到了 MYSQL 数据库。即使在屏幕截图中。所以很明显它的mysql查询。 @bhuvneshpattnaik
  • 您没有使用任何特定的面向对象语言或脚本语言,例如JSPHPJAVA。不要使用子查询或 JOIN 进行优化,而是从更容易优化整个代码库和数据检索时间的语言中获取帮助。
  • 显示创建表需要知道你有哪些索引。需要解释才能知道 MySQL 当前是如何执行查询的。此外,尽管您可能喜欢数据图像,但其他人喜欢看到他们习惯的表结构(例如,作为代码)。或者他们想使用代码,然后可以简单地使用它来创建表并运行/测试/修改您的代码。此外,您的描述与您的查询不匹配。如果您使用“其中dealer_visit_id=2660”(使用dealer_visit_id 作为主键),您将不会在1.5 秒内获得1000+ 条记录,只有一条。你可能会执行 1000 次吗?

标签: mysql sql datatables serverside-datatable


【解决方案1】:

您的语法很好,我认为您的查询没有问题。我做了比这更复杂的,有数百万条记录

我认为这归结为正确索引您的列。

使用 EXPLAIN 来研究是否使用了索引。

【讨论】:

  • 查询很好,因为它加载正确的数据但也太慢了。它正在做的是为每条记录执行子查询所以如果我有 1000 条记录要获取,查询将被执行两次,所以选择记录 2000 次
  • 添加有问题
  • 那是描述一个表。但是试试这个.... SHOW INDEX FROM [table_name] ;因为我想查看您表的当前索引;
  • 在“dvr_id”列上添加索引大大提高了速度。非常感谢。
【解决方案2】:

首先,您的查询在多个方面都不正确:

  • 子查询中的from 指的是列,而不是表。
  • group by 可以返回多行。

我想你想要:

select dv.*,
       (select count(*)
        from dealer_visit dv2
        where dv2.dvr_id = dv.dealer_visit_id
       ) as totalDVRs
from dealer_visit dv;

为了提高性能,您需要在dealer_visit(delaer_visit_id) 上建立索引。

假设 dealer_visit_id 是唯一的,那么在 MySQL 8+ 中,您应该改为:

select dv.*,
       count(dv.dvr_id) over (partition by dv.dvr_id) as totalDVRs
from dealer_visit dv;

【讨论】:

  • 感谢您指出我关于不正确的from 表名的错误。现在编辑问题。是的,您对我想要获取的内容是正确的。但是查询太慢了。但是在“dvr_id”列上添加索引大大提高了速度。
猜你喜欢
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-14
  • 2013-11-18
  • 2011-08-05
  • 2021-02-01
  • 1970-01-01
相关资源
最近更新 更多