为什么这个MySQL查询执行起来很慢?

时间:2017-05-12 20:45:58

标签: mysql sql performance mysqli

我提供了包含真实测试数据的PHP查询和数据库表。为什么MySQL查询的执行速度如此之慢?有什么我可以改变加快速度吗?执行时间约为40秒,表中约有2929条记录。

查询;

$invoice_details_query = mysqli_query($con,"SELECT i.*, 

ifnull(SUM(ip.invoice_payment_amount),0) as paid, 
(i.invoice_total_amount_exc_vat + i.invoice_total_vat_amount) - ifnull(SUM(ip.invoice_payment_amount),0) as due 
FROM accounts_invoice i 
LEFT JOIN accounts_invoice_payment ip 
ON ip.invoice_payment_invoice_id = i.invoice_id 
WHERE i.invoice_posted='1'
GROUP BY i.invoice_id 
HAVING due>0 
ORDER BY i.invoice_id ASC") or die(mysql_error());

$total = mysqli_num_rows($invoice_details_query);

数据库结构(无数据);

-- phpMyAdmin SQL Dump
-- version 4.6.6
-- https://www.phpmyadmin.net/
--
-- Host: localhost:3306
-- Generation Time: May 12, 2017 at 09:56 PM
-- Server version: 5.6.35
-- PHP Version: 5.6.30

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
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: `propsyst_main`
--

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

--
-- Table structure for table `accounts_invoice`
--

CREATE TABLE `accounts_invoice` (
  `invoice_id` int(11) NOT NULL,
  `invoice_token` varchar(40) COLLATE utf8_bin DEFAULT NULL,
  `invoice_customer_type` tinyint(4) DEFAULT NULL,
  `invoice_customer` int(11) DEFAULT NULL,
  `invoice_date` date DEFAULT NULL,
  `invoice_due_date` date DEFAULT NULL,
  `invoice_property_id` int(11) DEFAULT NULL,
  `invoice_tenancy_id` int(11) DEFAULT NULL,
  `invoice_branch` int(11) DEFAULT NULL,
  `invoice_payment_terms` tinyint(4) DEFAULT NULL,
  `invoice_notes` text COLLATE utf8_bin,
  `invoice_total_amount_exc_vat` decimal(10,2) DEFAULT NULL,
  `invoice_total_vat_amount` decimal(10,2) DEFAULT NULL,
  `invoice_posted` tinyint(4) DEFAULT '0',
  `invoice_overdue_reminders` tinyint(4) NOT NULL DEFAULT '1',
  `invoice_date_created` datetime DEFAULT NULL,
  `invoice_date_updated` datetime DEFAULT NULL,
  `invoice_date_posted` datetime DEFAULT NULL,
  `invoice_created_by` int(11) DEFAULT NULL,
  `invoice_updated_by` int(11) DEFAULT NULL,
  `invoice_posted_by` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `accounts_invoice`
--
ALTER TABLE `accounts_invoice`
  ADD PRIMARY KEY (`invoice_id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `accounts_invoice`
--
ALTER TABLE `accounts_invoice`
  MODIFY `invoice_id` int(11) NOT NULL AUTO_INCREMENT;
/*!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 */;

EXPLAIN ANALYZE;

 Current selection does not contain a unique column. Grid edit, checkbox, Edit, Copy and Delete features are not available. 

Your SQL query has been executed successfully.

explain accounts_invoice



invoice_id  int(11) NO  PRI     auto_increment  
invoice_token   varchar(40) YES             
invoice_customer_type   tinyint(4)  YES             
invoice_customer    int(11) YES             
invoice_date    date    YES             
invoice_due_date    date    YES             
invoice_property_id int(11) YES             
invoice_tenancy_id  int(11) YES             
invoice_branch  int(11) YES             
invoice_payment_terms   tinyint(4)  YES             
invoice_notes   text    YES             
invoice_total_amount_exc_vat    decimal(10,2)   YES             
invoice_total_vat_amount    decimal(10,2)   YES             
invoice_posted  tinyint(4)  YES     0       
invoice_overdue_reminders   tinyint(4)  NO      1       
invoice_date_created    datetime    YES             
invoice_date_updated    datetime    YES             
invoice_date_posted datetime    YES             
invoice_created_by  int(11) YES             
invoice_updated_by  int(11) YES             
invoice_posted_by   int(11) YES             

具有真实测试数据的数据库;

Download MySQL data

1 个答案:

答案 0 :(得分:1)

请为每张表提供SHOW CREATE TABLE。听起来你错过了以invoice_payment_invoice_id开头的任何索引。

此外,如果只发布一小部分发票,那么INDEX(invoice_posted, invoice_id)将是有益的。