由于查询性能下降?

时间:2014-01-27 06:51:00

标签: mysql sql indexing query-performance

请帮我改写下面的查询。

由于以下查询,我们遇到了性能问题。在此查询中,我们使用的是子查询。 请帮我重新编写,不带子查询。

查询是:

select 
    sum(a.order_count)
from
    (select 
        count(cart_id) as order_count, user_id
    from
        carts_archive
    where
        order_date > '2013-01-21 00:00:01'
            and user_id is not null
    group by user_id
    order by order_count desc) a
where
    a.order_count > 1;

我们也无法解释解释计划。

解释计划:

解释计划:

+----+-------------+---------------+-------+--------------------------------------------+------------------------+---------+------+---------+----------------------------------------------+
| id | select_type | table         | type  | possible_keys                              | key                    | key_len | ref  | rows    | Extra                                        |
+----+-------------+---------------+-------+--------------------------------------------+------------------------+---------+------+---------+----------------------------------------------+
|  1 | PRIMARY     | <derived2>    | ALL   | NULL                                       | NULL                   | NULL    | NULL | 1436430 | Using where                                  |
|  2 | DERIVED     | carts_archive | range | nk_cart_ach_user_id,pk_cart_ach_order_date | pk_cart_ach_order_date | 9       | NULL | 3552006 | Using where; Using temporary; Using filesort |
+----+-------------+---------------+-------+--------------------------------------------+------------------------+---------+------+---------+----------------------------------------------+
2 rows in set (2 min 50.33 sec)

表格结构:

mysql> show create table carts_archive\G
*************************** 1. row ***************************
       Table: carts_archive
Create Table: CREATE TABLE `carts_archive` (
  `row_mod` datetime DEFAULT NULL,
  `row_create` datetime DEFAULT NULL,
  `order_date` datetime DEFAULT NULL,
  `billing_zip` varchar(10) COLLATE latin1_bin DEFAULT NULL,
  `billing_address` varchar(200) COLLATE latin1_bin DEFAULT NULL,
  `billing_home_phone` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `billing_email` varchar(100) COLLATE latin1_bin DEFAULT NULL,
  `status` varchar(30) COLLATE latin1_bin DEFAULT NULL,
  `website_id` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `discount_program` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `credit_card_exp_year` varchar(4) COLLATE latin1_bin DEFAULT NULL,
  `billing_country` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `add_client_flag` varchar(1) COLLATE latin1_bin DEFAULT NULL,
  `billing_last_name` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `billing_work_phone` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `total_charge` float(10,2) DEFAULT NULL,
  `add_newsletter_flag` varchar(1) COLLATE latin1_bin DEFAULT NULL,
  `cart_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `discount_first_name` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `markcode` int(11) DEFAULT NULL,
  `discount_account_junk` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `gift_cert_junk` varchar(30) COLLATE latin1_bin DEFAULT NULL,
  `credit_card_name` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `billing_work_phone_ext` varchar(10) COLLATE latin1_bin DEFAULT NULL,
  `billing_state` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `billing_first_name` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `order_id` varchar(30) COLLATE latin1_bin DEFAULT NULL,
  `discount_last_name` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `credit_card_exp_month` varchar(2) COLLATE latin1_bin DEFAULT NULL,
  `credit_card_number` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `billing_city` varchar(100) COLLATE latin1_bin DEFAULT NULL,
  `credit_card_type` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `discount_account` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `asnbuyer` varchar(70) COLLATE latin1_bin DEFAULT NULL,
  `buyercookie` varchar(70) COLLATE latin1_bin DEFAULT NULL,
  `expire_date` datetime DEFAULT NULL,
  `security_string` varchar(255) COLLATE latin1_bin DEFAULT NULL,
  `user_information` varchar(255) COLLATE latin1_bin DEFAULT NULL,
  `track_id` varchar(255) COLLATE latin1_bin DEFAULT NULL,
  `gift_cert` varchar(255) COLLATE latin1_bin DEFAULT NULL,
  `billing_address2` varchar(100) COLLATE latin1_bin DEFAULT NULL,
  `visited_signup` varchar(1) COLLATE latin1_bin DEFAULT NULL,
  `paypal_email_junk` varchar(127) COLLATE latin1_bin DEFAULT NULL,
  `used_saved_cc_flag` varchar(1) COLLATE latin1_bin DEFAULT NULL,
  `paypal_auth_amount_junk` float DEFAULT NULL,
  `bml_auth_code_junk` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `bml_approve_amount_junk` float DEFAULT NULL,
  `bml_account_id_junk` varchar(30) COLLATE latin1_bin DEFAULT NULL,
  `bml_order_number_junk` varchar(22) COLLATE latin1_bin DEFAULT NULL,
  `alt_reference_num` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `alt_account_id` varchar(200) COLLATE latin1_bin DEFAULT NULL,
  `alt_approval_amount` float DEFAULT NULL,
  `alt_points_used` float DEFAULT NULL,
  `alt_auth_id` varchar(30) COLLATE latin1_bin DEFAULT NULL,
  `alt_redemption_rate` float DEFAULT NULL,
  `cvv_response_code` varchar(50) COLLATE latin1_bin DEFAULT NULL,
  `cvv_indicator_value` varchar(1) COLLATE latin1_bin DEFAULT NULL,
  `language_id` varchar(10) COLLATE latin1_bin DEFAULT 'ENUS',
  `gc_trans_id` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `gc_auth_date` datetime DEFAULT NULL,
  `gc_pin` varchar(20) COLLATE latin1_bin DEFAULT NULL,
  `gift_cert_value` float DEFAULT NULL,
  UNIQUE KEY `pk_cart_ach_cart_id` (`cart_id`),
  KEY `nk_cart_ach_user_id` (`user_id`),
  KEY `pk_cart_ach_order_date` (`order_date`),
  KEY `carts_archive_n1` (`row_mod`),
  KEY `order_id_n1` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin
1 row in set (0.00 sec)

3 个答案:

答案 0 :(得分:1)

我没有看到在子查询中使用order by子句的任何用法。 有关索引的表中记录数量的信息将有所帮助,或解释计划将有所帮助。

也可以尝试使用下面稍微修改过的sql

选择     总和(a.order_count) 从     (选择         count(cart_id)为order_count,user_id     从         carts_archive     哪里         order_date&gt; '2013-01-21 00:00:01'             并且user_id不为null     group by user_id     有计数(card_id)&gt; 1)a

答案 1 :(得分:0)

尝试创建索引,如下所示,然后查看EXPLAIN计划

CREATE INDEX idx_order_date_user_id ON carts_archive(order_date,user_id);

答案 2 :(得分:0)

我对这个问题的了解是有限的,但是当我们遇到类似的问题时,我发现SQL SERVER 2012具有自动索引或者在未指定时与索引相关的一些问题,因此添加主键或任何类型的索引 ,没有正确的索引顺序可能会有性能问题

也请参考 SQL Server 2012 Performance Issue