Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 优化SQL查询_Mysql_Join - Fatal编程技术网

Mysql 优化SQL查询

Mysql 优化SQL查询,mysql,join,Mysql,Join,我正在尝试优化这个缓慢的查询(>2s) 这是我使用EXPLAIN时的输出: id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE c index_merge PRIMARY,crmentity_smownerid_idx,crmentity_deleted_smownerid_idx,crmentity_smownerid_deleted_idx crmenti

我正在尝试优化这个缓慢的查询(>2s)

这是我使用EXPLAIN时的输出:

id  select_type table   type    possible_keys   key key_len ref rows    Extra   
1   SIMPLE  c   index_merge PRIMARY,crmentity_smownerid_idx,crmentity_deleted_smownerid_idx,crmentity_smownerid_deleted_idx crmentity_smownerid_idx,crmentity_deleted_smownerid_idx 4,8 NULL    91  Using intersect(crmentity_smownerid_idx,crmentity_deleted_smownerid_idx); Using where; Using index
1   SIMPLE  mt  ref activityid  activityid  4   pharex.c.crmid  60  
1   SIMPLE  mtu ref dept_idx    dept_idx    5   const   1530    Using where
它使用的是我创建的索引(dept_idx),但对1380384条记录的数据集运行查询仍然需要2秒钟以上。是否有另一种以最佳方式表达此查询的方法

更新:根据David的建议,查询现在只需几毫秒,而不是运行超过2秒(实际上,MySQL 5.0版的查询时间为51秒)

  • 我将使用连接重写查询。它更清晰,给优化器提供了更好的机会
  • 月(mtu.ts)=2和年(mtu.ts)=年(现在())-最好在..之间使用mtu.ts。。和

  • WHERE
    子句中最有选择性的部分是什么?也就是说,哪个条件会从结果集中删除最有潜力的项

    我猜这是
    mtu.ts
    过滤器。如果这是真的,您还应该为
    mtu.ts
    列编制索引,并尝试以可以使用索引的方式对此进行约束;例如,使用运算符

    其他提示:

    • 使用
      join将join子句直接附加到join。。。在()上
      ,这使得查询更易于阅读,无论是对于人还是优化器
    • 避免在查询中计算常量,如
      YEAR(NOW())
    • 避免WHERE子句中所选列的函数,如
      MONTH(mtu.ts)
      。这降低了大量使用索引的可能性
    • 规范化您的数据,以避免出现诸如mtu.dept='GUN'或mtu.dept='GUN'之类的套管问题。;一个
      更新mtu设置dept=lower(dept)
      和一个适当的
      检查dept=lower(dept)
      将有助于避免这种疯狂

    您能将文本字符串更改为一个数字吗?

    我能看到的最明显的解决方案是将COUNT(*)更改为只包含一个字段名,否则您的索引可能几乎没有用处

    作为一般原则,分析此类问题的一个好方法是了解匹配的数据,了解其重要性

    也就是说,对查询进行排序,以便最有选择性的事情首先发生。 在您的数据中,dept='GUN'或userId可能是28

    Lasty,你是否考虑过加入MT和MTU而不是过滤?
    这可能会使您的查询速度大大加快,因为您将限制需要进行日期比较的数据量。

    我会编写
    其中lower(mtu.dept)=“gun”和…
    ,但我认为您的数据库已经以这种方式对其进行了优化。我发现,至少在Oracle中,在查询的左侧使用lower会导致速度大幅降低。无论它是否比额外的字符串比较更慢……对列使用lower()是一种不使用任何索引的好方法。这可以解释你的慢下来。格雷厄姆,大卫,你当然是对的。我不会删除我的注释,这样反模式仍然有效;-)贴得太快了,基本上就是大卫·施密特和伯纳尔所说的!你会怎么重写这个?再次感谢。请从c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.cc.deleted=0和c.smownerid=28谢谢这个例子。我在PHP中创建了一个函数来获取月份的开始日期和结束日期,并在“BETWEEN”语句中使用它。
    id  select_type table   type    possible_keys   key key_len ref rows    Extra   
    1   SIMPLE  c   index_merge PRIMARY,crmentity_smownerid_idx,crmentity_deleted_smownerid_idx,crmentity_smownerid_deleted_idx crmentity_smownerid_idx,crmentity_deleted_smownerid_idx 4,8 NULL    91  Using intersect(crmentity_smownerid_idx,crmentity_deleted_smownerid_idx); Using where; Using index
    1   SIMPLE  mt  ref activityid  activityid  4   pharex.c.crmid  60  
    1   SIMPLE  mtu ref dept_idx    dept_idx    5   const   1530    Using where