mysql - 尽管建立了索引,但使用多个表连接进行查询仍花费太多时间

标签 mysql database join query-optimization query-performance

查询-

SELECT SUM(sale_data.total_sale) as totalsale, `sale_data_temp`.`customer_type_cy` as `customer_type`, `distributor_list`.`customer_status` FROM `distributor_list` LEFT JOIN `sale_data` ON `sale_data`.`depo_code` = `distributor_list`.`depo_code` and `sale_data`.`customer_code` = `distributor_list`.`customer_code` LEFT JOIN `sale_data_temp` ON `distributor_list`.`address_coordinates` = `sale_data_temp`.`address_coordinates` LEFT JOIN `item_master` ON `sale_data`.`item_code` = `item_master`.`item_code` WHERE `invoice_date` BETWEEN "2017-04-01" and "2017-11-01" AND `item_master`.`id_category` = 1 GROUP BY `distributor_list`.`address_coordinates`

查询,用格式重写。

SELECT SUM(sale_data.total_sale) as totalsale,
       sale_data_temp.customer_type_cy as customer_type,
       distributor_list.customer_status
  FROM distributor_list
  LEFT JOIN sale_data
             ON sale_data.depo_code = distributor_list.depo_code
            and sale_data.customer_code = distributor_list.customer_code
  LEFT JOIN sale_data_temp
            ON distributor_list.address_coordinates = sale_data_temp.address_coordinates
  LEFT JOIN item_master
           ON sale_data.item_code = item_master.item_code
 WHERE invoice_date BETWEEN "2017-04-01" and "2017-11-01"
   AND item_master.id_category = 1
 GROUP BY distributor_list.address_coordinates

DESC-

此查询运行需要 7.5 秒。我的应用程序包含 3-4 个此类查询。因此服务器上的加载时间接近 1 分钟。 我的销售数据表包含 450K 条记录。 经销商列表包含970条记录 Item master 包含 7774 条记录,sale_data_temp 包含 324 条记录。 我正在使用索引,但它没有用于销售数据表。 从解释 sql 可以明显看出,所有 400K 记录都被搜索。 如果我减少 BETWEEN 子句的持续时间,那么销售数据表将使用日期索引,否则它将扫描所有 400K 行。 01-04-2017 和 01-11-2017 之间的行数为 84000,但仍扫描 400K 行。

MYSQL 解释- MYSQL EXPLAIN Statement

我已修改查询两次,但没有成功。

修改1:

SELECT SUM(sale_data.total_sale) as totalsale, `sale_data_temp`.`customer_type_cy` as `customer_type`, `distributor_list`.`customer_status` FROM `distributor_list` LEFT JOIN `sale_data` ON `sale_data`.`depo_code` = `distributor_list`.`depo_code` and `sale_data`.`customer_code` = `distributor_list`.`customer_code` AND `invoice_date` BETWEEN "2017-04-01" and "2017-11-01" LEFT JOIN `sale_data_temp` ON `distributor_list`.`address_coordinates` = `sale_data_temp`.`address_coordinates` LEFT JOIN `item_master` ON `sale_data`.`item_code` = `item_master`.`item_code` WHERE `item_master`.`id_category` = 1 GROUP BY `distributor_list`.`address_coordinates`

修改 2

SELECT SQL_NO_CACHE SUM( sd.total_sale ) AS totalsale, `sale_data_temp`.`customer_type_cy` AS `customer_type` , `distributor_list`.`customer_status` FROM `distributor_list` LEFT JOIN (SELECT * FROM `sale_data` WHERE `invoice_date` BETWEEN "2017-04-01" AND "2017-11-01")sd ON `sd`.`depo_code` = `distributor_list`.`depo_code` AND `sd`.`customer_code` = `distributor_list`.`customer_code` LEFT JOIN `sale_data_temp` ON `distributor_list`.`address_coordinates` = `sale_data_temp`.`address_coordinates` LEFT JOIN `item_master` ON `sd`.`item_code` = `item_master`.`item_code` WHERE `item_master`.`id_category` =1 GROUP BY `distributor_list`.`address_coordinates`

这是我的销售指数数据表 mysql EXPLAIN AND INDEXES IMAGE

最佳答案

查看EXPLAIN结果 View 的key列 - 目前没有使用任何键,因此MySQL没有使用任何索引来过滤行,因此它在每个查询上扫描整个表。这就是为什么花了这么长时间。

我查看了您与 sale_data 索引相关的第一个查询。看来您需要在此表上创建一个新的复合索引,其中仅包含以下列:

depo_codecustomer_codeitem_codeinvoice_datetotal_sale

我建议您将此索引命名为 test1 并尝试修改列的顺序,并每次使用 EXPLAIN EXTENDED 再次进行测试,直到获得选定的键 -您希望看到索引 test1 已在 key 列中选择。

参见this answer这之前对我有帮助,它将帮助您了解正确排序综合指数的重要性。

查看单字段索引的基数,这是我为您提供要应用的正确索引的最佳尝试:

ALTER TABLE `sale_data` ADD INDEX `test1` (`item_code`, `customer_code`, `invoice_date`, `depo_code`, `total_sale`);

祝你任务顺利!

关于mysql - 尽管建立了索引,但使用多个表连接进行查询仍花费太多时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47072476/

相关文章:

sql - 优化数据库类型以压缩数据库(SQLite)

database - SELECT 多行,其中日期大于前一行的 X 分钟

mysql - 将 gem mysql12 安装到 ruby​​ 时出错

mysql - SQL中连接垂直表和水平表的最佳方法

NHibernate - 简单的连接查询

mysql - 为什么这个 MySQL 查询在 phpmyadmin 中有效,但在我的 php 脚本中没有返回任何内容?

java - 如何告诉 Spring Boot 使用另一个数据库进行测试?

mysql - 在 MySQL 中使用 HSQLDB 传输工具时出现问题

javascript - 无法使用 jQuery load() 将 php 结果加载到 div

php - MySQL 语句返回 true 但不插入