【问题标题】:Can anyone help me figure out why these SQL queries are taking so long?谁能帮我弄清楚为什么这些 SQL 查询需要这么长时间?
【发布时间】:2014-05-31 02:12:56
【问题描述】:

以下 sn-p 代码取自我的 global.class.php 文件。当搜索“类型”等于“邮政编码”或“零件编号”时,我目前遇到执行 SQL 查询所需时间的问题。请参阅下面的 sn-p 以了解包括处理时间在内的说明。

function findOrder($type, $query) {
    $db = new db;
    $tasks = new tasks;
    
    if($type == 'order-id') {
        return $db->query("
            SELECT details.id, details.order_id, users.title, users.first_name, users.last_name, details.date_time, details.status
            FROM orders_details AS details
            LEFT JOIN orders_users AS users
            ON users.order_id = details.order_id
            WHERE details.order_id LIKE '$query'
            ORDER BY id DESC
        ");
    } elseif($type == 'postcode') {
        return $db->query("                
            SELECT addresses.id AS id, addresses.order_id, addresses.postcode, users.title, users.first_name, users.last_name, details.date_time, details.status 
            FROM orders_users as users 
            LEFT JOIN orders_details as details 
            ON users.order_id = details.order_id
            LEFT JOIN orders_addresses as addresses 
            ON addresses.order_id = details.order_id
            WHERE REPLACE(addresses.postcode, ' ','') LIKE '$query'
            ORDER BY id DESC
        ");
    } elseif($type == 'surname') {
        return $db->query("
            SELECT users.id AS id, users.order_id, users.title, users.first_name, users.last_name, details.date_time, details.status
            FROM orders_users AS users
            LEFT JOIN orders_details AS details 
            ON users.order_id = details.order_id
            WHERE REPLACE(users.last_name, ' ','') LIKE '$query'
            ORDER BY id DESC
        ");
    } elseif($type == 'part-number') {
        $query = $tasks->getProductID($query); //Change $query to product ID
        return $db->query("
            SELECT carts.id AS id, carts.order_id, carts.product_id, users.title, users.first_name, users.last_name, details.date_time, details.status
            FROM orders_users AS users
            LEFT JOIN orders_details AS details 
            ON users.order_id = details.order_id
            LEFT JOIN orders_carts AS carts 
            ON carts.order_id = details.order_id
            WHERE carts.product_id = '$query'
            ORDER BY id DESC
        ");
    }
    
}

请看下面的执行时间:

type = order-id
query = 106696 //(1 result returned)
page time = 0.0074
sql time = 0.0065

type = surname
query = smith //(23 results returned)
page time = 0.0725
sql time = 0.0700

type = postcode
query = **hidden** //(1 result returned)
page time = 2.6505 
sql time = 0.0125

type = part-number
query = **hidden** //(13 results returned)
page time = 2.8564 //(I also checked the getProductID() function, and this takes 0.0123) 
sql time = 0.0470

页面时间是调用 findOrder('type', 'query'); 所花费的时间

SQL 时间是我直接在 phpMyAdmin 中重复查询所用的时间。

我可以看到订单 ID 和姓氏查询与邮政编码和零件号查询之间的唯一区别是有一个额外的 LEFT JOIN。这并不能解释为什么在 phpMyAdmin 中执行的相同查询返回得如此之快。我不知道为什么要花将近 3 秒才能返回一个应该花费不到 50 毫秒的查询。

其他人能明白为什么会这样吗?如果你还需要什么,请告诉我。

按要求解释查询

订单号:

id select_type table type possible_keys key key_len ref rows Extra

1 简单细节 ALL NULL NULL NULL NULL 1975 使用 where;使用临时的;使用文件排序

1 简单用户 ALL NULL NULL NULL NULL 1992

姓氏:

1 SIMPLE 用户 ALL NULL NULL NULL NULL 1992 使用 where;使用临时的;使用文件排序

1 简单的细节 ALL NULL NULL NULL NULL 1975

邮编:

1 简单细节 ALL NULL NULL NULL NULL 1966 使用临时;使用文件排序

1 SIMPLE 用户 ALL NULL NULL NULL NULL 1983 使用 where;使用连接缓冲区

1 简单地址 ALL NULL NULL NULL NULL 1983 使用 where;使用连接缓冲区

零件编号:

1 简单细节 ALL NULL NULL NULL NULL 1975 使用临时;使用文件排序

1 SIMPLE 用户 ALL NULL NULL NULL NULL 1992 使用 where;使用连接缓冲区

1 SIMPLE carts ALL NULL NULL NULL NULL 3611 使用where;使用连接缓冲区

根据要求创建表查询

--
-- Table structure for table `orders_addresses`
--

CREATE TABLE IF NOT EXISTS `orders_addresses` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` varchar(255) NOT NULL,
  `active` tinyint(4) NOT NULL,
  `company` varchar(255) NOT NULL,
  `line1` varchar(255) NOT NULL,
  `line2` varchar(255) NOT NULL,
  `line3` varchar(255) NOT NULL,
  `town` varchar(255) NOT NULL,
  `county` varchar(255) NOT NULL,
  `postcode` varchar(255) NOT NULL,
  `country` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2004 ;

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

--
-- Table structure for table `orders_carts`
--

CREATE TABLE IF NOT EXISTS `orders_carts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` varchar(255) NOT NULL,
  `product_id` int(11) NOT NULL,
  `part_name` varchar(255) NOT NULL,
  `qty_ord` int(11) NOT NULL,
  `qty_rcv` int(11) NOT NULL,
  `cost_net` int(11) NOT NULL,
  `cost_gross` int(11) NOT NULL,
  `status` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3629 ;

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

--
-- Table structure for table `orders_details`
--

CREATE TABLE IF NOT EXISTS `orders_details` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` varchar(255) NOT NULL,
  `transaction_id` varchar(255) NOT NULL,
  `date_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `postage` int(11) NOT NULL,
  `sub_total` int(11) NOT NULL,
  `cart_vat` int(11) NOT NULL,
  `total` int(11) NOT NULL,
  `status` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1985 ;

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

--
-- Table structure for table `orders_users`
--

CREATE TABLE IF NOT EXISTS `orders_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` varchar(255) NOT NULL,
  `active` tinyint(4) NOT NULL,
  `title` varchar(255) NOT NULL,
  `first_name` varchar(255) NOT NULL,
  `last_name` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `telephone` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2005 ;

【问题讨论】:

  • 显示EXPLAIN query 输出的内容,还添加了一些带有索引的表定义。 phpMyAdmin 是否默认添加LIMIT?尝试使用mysql 客户端并执行这些查询。不要在 phpmyadmin 中测量它。
  • 我已经添加了您要求的解释查询输出,我将登录到服务器并在我有几分钟空闲时通过 mysql 执行这些查询。
  • 您能否附上CREATE TABLE 对这些表的查询?
  • 我已经添加了 CREATE TABLE 查询。

标签: php mysql phpmyadmin


【解决方案1】:

试试这个,

function findOrder($type, $query) {
$db = new db;
$tasks = new tasks;

if($type == 'order-id') {
    return $db->query("
        SELECT details.id, details.order_id, users.title, users.first_name, users.last_name, details.date_time, details.status
        FROM orders_details AS details
        LEFT JOIN orders_users AS users
        ON users.order_id = details.order_id
        WHERE details.order_id LIKE '$query'
        ORDER BY id DESC
    ");
} elseif($type == 'postcode') {
    return $db->query("                
        SELECT addresses.id AS id, addresses.order_id, addresses.postcode, users.title, users.first_name, users.last_name, details.date_time, details.status 
        FROM orders_users as users 
        LEFT JOIN orders_details as details 
        ON details.order_id = users.order_id
        LEFT JOIN orders_addresses as addresses 
        ON details.order_id = addresses.order_id
        WHERE REPLACE(addresses.postcode, ' ','') LIKE '$query'
        ORDER BY id DESC
    ");
} elseif($type == 'surname') {
    return $db->query("
        SELECT users.id AS id, users.order_id, users.title, users.first_name, users.last_name, details.date_time, details.status
        FROM orders_users AS users
        LEFT JOIN orders_details AS details 
        ON users.order_id = details.order_id
        WHERE REPLACE(users.last_name, ' ','') LIKE '$query'
        ORDER BY id DESC
    ");
} elseif($type == 'part-number') {
    $query = $tasks->getProductID($query); //Change $query to product ID
    return $db->query("
        SELECT carts.id AS id, carts.order_id, carts.product_id, users.title, users.first_name, users.last_name, details.date_time, details.status
        FROM orders_users AS users
        LEFT JOIN orders_details AS details 
        ON details.order_id = users.order_id
        LEFT JOIN orders_carts AS carts 
        ON details.order_id = carts.order_id
        WHERE carts.product_id = '$query'
        ORDER BY id DESC
    ");
}

}

【讨论】:

  • 不确定你做了什么改变,但我用相同的结果替换了我的类文件中的函数,邮政编码和零件号不到 3 秒。
  • 是的,它可以工作,但与现在完全一样。仍然存在邮政编码和零件编号的执行时间问题。
  • 好的。让我访问您的 PC 或让我访问您的项目,以便继续编写更好的查询。
  • 试试这个查询邮政编码“SELECTaddresses.id AS id,addresses.order_id,addresses.postcode,users.title,users.first_name,users.last_name,details.date_time,details.status FROM orders_addresses作为地址 LEFT JOIN orders_details 作为 details ON addresses.order_id = details.order_id LEFT JOIN orders_users AS users ON users.order_id = details.order_id WHERE replace(addresses.postcode, ' ', '' ) LIKE '20138' ORDER BY id DESC"
  • 解决了!!你可以对零件号做同样的事情吗?还有你是怎么做到的?大声笑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 2011-08-27
  • 2015-08-11
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多