针对极慢查询的 MySQL 查询优化

标签 mysql optimization query-optimization execution-time

我是一名网络开发人员,我是第一次在 SO 上发帖。

今天我请求你的帮助,因为我已经尝试了所有的可能性,但没有成功。

我创建了一个供销售人员在现场使用的 SAAS 网络应用程序,它包括一个离线版本,用户无需连接即可使用它。

随着数据库越来越大,查询的执行时间也越来越长。

今天我遇到了一个大问题,即当用户尝试显示查询结果时,查询会导致超时。

所以,这是转储:

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

-- 86 rows
CREATE TABLE t2 (
  id_t2 int(11) NOT NULL,
  quantite_t2 int(11) NOT NULL,
  ca_t2 decimal(10,2) NOT NULL,
  date_t2 date NOT NULL,
  import_t2 datetime NOT NULL,
  id_enseigne int(11) NOT NULL,
  id_t3 int(11) NOT NULL,
  annee_t2 int(11) NOT NULL,
  mois_t2 int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 2012065 rows
CREATE TABLE t1 (
  id_t2 int(11) NOT NULL,
  id_t0 bigint(20) NOT NULL,
  id_t4 bigint(20) NOT NULL,
  quantite_t1 int(11) NOT NULL,
  ca_t1 decimal(10,2) NOT NULL,
  pvc_moyen_t1 float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 388 rows
CREATE TABLE t4 (
  id_t4 int(11) NOT NULL,
  lib_t4 text NOT NULL,
  libcourt_t4 varchar(255) NOT NULL,
  ean_t4 varchar(255) NOT NULL,
  pcb_t4 int(11) NOT NULL,
  pcb2_t4 int(11) NOT NULL,
  fam_t4 varchar(255) NOT NULL,
  gam_t4 varchar(255) NOT NULL DEFAULT '0',
  stat_t4 int(11) NOT NULL DEFAULT 1,
  vmh_t4 decimal(10,2) NOT NULL,
  detail_t4 text NOT NULL,
  ingr_t4 text NOT NULL,
  weight_t4 float NOT NULL,
  lifetime_t4 varchar(255) NOT NULL,
  pmc1_t4 float NOT NULL,
  pmc2_t4 float NOT NULL,
  dim_t4 decimal(10,2) NOT NULL,
  ordre_t4 int(11) NOT NULL,
  created_t4 datetime NOT NULL,
  updated_t4 datetime NOT NULL,
  updated_img_t4 datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 1 row
CREATE TABLE t3 (
  id_t3 int(11) NOT NULL,
  nom_t3 text NOT NULL,
  stat_t3 int(11) NOT NULL,
  created_t3 datetime NOT NULL,
  deleted_t3 datetime NOT NULL,
  updated_t3 datetime NOT NULL,
  ip_create_t3 text NOT NULL,
  ip_delete_t3 text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


ALTER TABLE t2
  ADD PRIMARY KEY (id_t2),
  ADD KEY annee_t2 (annee_t2,mois_t2,date_t2);

ALTER TABLE t1
  ADD PRIMARY KEY (id_t2,id_t0,id_t4);

ALTER TABLE t4
  ADD PRIMARY KEY (id_t4,ean_t4),
  ADD KEY ean_t4 (ean_t4),
  ADD KEY id_t4 (id_t4);

ALTER TABLE t3
  ADD PRIMARY KEY (id_t3);


ALTER TABLE t2
  MODIFY id_t2 int(11) NOT NULL AUTO_INCREMENT;

ALTER TABLE t4
  MODIFY id_t4 int(11) NOT NULL AUTO_INCREMENT;

ALTER TABLE t3
  MODIFY id_t3 int(11) NOT NULL AUTO_INCREMENT;

COMMIT;

下面执行的查询大约需要 4 分钟才能执行:

-- execution time 228 seconds
SELECT SUM(t1.ca_t1) AS ca_t4, SUM(t1.quantite_t1) AS qte_t4,
       t4.fam_t4, t4.gam_t4, t4.lib_t4, t4.ean_t4, t4.id_t4,
       t2.annee_t2, t2.mois_t2, COUNT(t1.id_t0) AS count_mag,
       t3.id_t3, t3.nom_t3
FROM t1 t1
INNER JOIN t2 t2 ON t2.id_t2 = t1.id_t2
LEFT JOIN t3 t3 ON t2.id_t3 = t3.id_t3
INNER JOIN t4 t4 ON t1.id_t4 = t4.ean_t4
WHERE t2.date_t2 BETWEEN "2017-05-01" AND "2019-05-01"
GROUP BY t2.annee_t2, t2.mois_t2, t4.id_t4
ORDER BY ca_t4 DESC;

我尝试了所有我知道的优化来帮助我减少执行时间,但没有成功...

EXPLAIN 显示了这一点:

id  select_type    table    type      possible_keys    key        key_len    ref            rows    Extra
1   SIMPLE         t2       ALL       PRIMARY          NULL       NULL       NULL           86      Using where; Using temporary; Using filesort
1   SIMPLE         t3       eq_ref    PRIMARY          PRIMARY    4          db.t2.id_t3    1       
1   SIMPLE         t1       ref       PRIMARY,id_t2    PRIMARY    4          db.t2.id_t2    11266   
1   SIMPLE         t4       ALL       ean_t4           NULL       NULL       NULL           388     Using where; Using join buffer (flat, BNL join)

谢谢你们的帮助。

最佳答案

这看起来像是一个相当复杂的查询,有多个地方会减慢它的速度。但是,我注意到的第一件事是必须进行双重查找才能使用 annee_2 索引,这可能就是它没有使用它的原因。

尝试将 id_t3 添加到表 t2 的该索引的末尾:

(annee_t2,mois_t2,date_t2,id_t3)

这应该允许优化使用该索引。

再次运行查询(两次,以填充缓冲区缓存,仅报告第二次结果),如果它没有得到充分改善,则发布新的 EXPLAIN 计划。

关于针对极慢查询的 MySQL 查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56888360/

相关文章:

php - 苹果推送 PHP : No all notifications received

php - 从 MySQL 查询中添加

mysql - 同步调用sql查询

sql - counter_cache has_many_through sql优化,减少sql查询次数

javascript - Angular 1.5 和多重嵌套数据结构

mysql - 是否可以优化这个MySql查询

mysql - 评估mysql日期范围

c - 如果全局变量被中断修改,是否真的需要 volatile 修饰符?

oracle - 如何描述关系数据库中的性能问题?

mysql - 如何避免使用此基本内部联接进行全表扫描?