0

SQLでヒントとしてインデックスを使用/強制しても、cli.clitypeとc.cliが選択されない理由は何ですか。以下のクエリでのみ 1634 をフェッチするために、4 秒で出力が得られます。5.5.25.log を使用しています。提案してください。

mysql> explain SELECT   DATE(sr.`date`),   v.company_name,   c.cli,   COUNT(*),   c.charge,   SUM(c.`charge`) FROM subscriptionrequest AS sr, cli AS c ,   vendor AS v WHERE sr.cli = c.cli     AND sr.secretkey = v.secretkey     AND sr.`date` BETWEEN'2012-03-12 00:00:00' AND '2012-10-13 00:00:00' and c.clitype = 'chargemo' GROUP BY DATE(sr.`date`), sr.secretkey,c.cli;
+----+-------------+-------+------+-----------------------------------------------+----------------+---------+----------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys                                 | key            | key_len | ref                        | rows | Extra                                        |
+----+-------------+-------+------+-----------------------------------------------+----------------+---------+----------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | c     | ALL  | idx_cli                                       | NULL           | NULL    | NULL                       |  115 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | sr    | ref  | idx_subreq_key,idx_subreq_cli,idx_subreq_date | idx_subreq_cli | 53      | crystal_du_sm.c.cli        |  869 | Using where                                  |
|  1 | SIMPLE      | v     | ref  | secretkey_idx                                 | secretkey_idx  | 52      | crystal_du_sm.sr.secretkey |    1 | Using where                                  |
+----+-------------+-------+------+-----------------------------------------------+----------------+---------+----------------------------+------+----------------------------------------------+
3 rows in set (0.00 sec)
mysql> show indexes from cli;
+-------+------------+--------------+--------------+-------------+-----------+---------     ----+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name     | Seq_in_index | Column_name | Collation |      Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
 +-------+------------+--------------+--------------+-------------+-----------+--------    -----+----------+--------+------+------------+---------+---------------+
| cli   |          0 | PRIMARY      |            1 | idcli       | A         |             115 |     NULL | NULL   |      | BTREE      |         |               |
| cli   |          1 | idx_cli      |            1 | cli         | A         |         115 |     NULL | NULL   |      | BTREE      |         |               |
| cli   |          1 | cli_type_idx |            1 | clitype     | A         |         115 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------+------------+--------------+--------------+-------------+-----------+---------     ----+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)    


mysql> show create table cli;

| cli   | CREATE TABLE `cli` (
`idcli` bigint(255) NOT NULL AUTO_INCREMENT,
`cli` varchar(256) NOT NULL,
`type` enum('SDMF','MDMF') NOT NULL DEFAULT 'SDMF',
`priority` enum('realtime','high','normal','low','ignore') NOT NULL DEFAULT 'normal',
`status` enum('active','inactive','suspended','deleted') NOT NULL DEFAULT 'active',
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`description` text,
`charge` float DEFAULT '0',
`clitype` enum('chargemo','freemo') DEFAULT 'freemo',
PRIMARY KEY (`idcli`),
KEY `idx_cli` (`cli`),
KEY `cli_type_idx` (`clitype`)
) ENGINE=InnoDB AUTO_INCREMENT=117 DEFAULT CHARSET=latin1 |

1 row in set (0.00 sec)

mysql> show create table vendor;
| vendor | CREATE TABLE `vendor` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(256) NOT NULL,
`company_name` varchar(256) DEFAULT NULL,
`phone_no` varchar(256) DEFAULT NULL,
`status` enum('active','inactive','suspended','deleted') DEFAULT 'active',
`mo` bigint(255) NOT NULL,
`mt` bigint(255) NOT NULL,
`used_mo` bigint(255) DEFAULT '0',
`used_mt` bigint(255) DEFAULT '0',
`start_time` timestamp NULL DEFAULT '0000-00-00 00:00:00',
`end_time` timestamp NULL DEFAULT '0000-00-00 00:00:00',
`secretkey` varchar(50) NOT NULL,
`callback_url` text,
`payment_callback_url` text,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`userid` int(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `secretkey_idx` (`secretkey`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1 |

1 row in set (0.00 sec)

| subscriptionrequest | CREATE TABLE `subscriptionrequest` (
`id` bigint(255) unsigned NOT NULL AUTO_INCREMENT,
`ipaddress` varchar(256) CHARACTER SET latin1 NOT NULL DEFAULT '0.0.0.0',
`message` text,
`msisdn` varchar(50) CHARACTER SET latin1 DEFAULT NULL,
`mode` varchar(50) CHARACTER SET latin1 DEFAULT NULL,
`cli` varchar(50) CHARACTER SET latin1 DEFAULT NULL,
`transactionid` varchar(100) DEFAULT NULL,
`secretkey` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`error_code` int(10) DEFAULT NULL,
`success` int(10) NOT NULL DEFAULT '0',
`status` enum('waiting','processing','completed','moexceeds','reject') DEFAULT     'waiting',
PRIMARY KEY (`id`),
KEY `idx_subreq_key` (`secretkey`),
KEY `idx_subreq_status` (`status`),
KEY `idx_subreq_transid` (`transactionid`),
KEY `idx_subreq_cli` (`cli`),
KEY `idx_subreq_date` (`date`)
) ENGINE=InnoDB AUTO_INCREMENT=1594161 DEFAULT CHARSET=utf8 |

刹那のために ---

mysql> explain SELECT DATE(sr.`date`) AS sr_date, v.company_name, c.cli, 
->   COUNT(*) AS cnt, c.charge, 
->   SUM(c.`charge`) AS charge_sum 
->   FROM 
->   subscriptionrequest AS sr 
->   JOIN cli AS c ON sr.cli = c.cli     
->   JOIN vendor AS v ON sr.secretkey = v.secretkey
->   WHERE 
->   sr.`date` >= '2012-03-12' AND sr.`date` <= '2012-10-13' 
->   AND c.clitype = 'chargemo' 
->   GROUP BY DATE(sr.`date`), sr.secretkey, c.cli;
+----+-------------+-------+------+-----------------------------+----------------+---------     +---------------------------+-------+---------------------------------+
| id | select_type | table | type | possible_keys               | key            | key_len     | ref                       | rows  | Extra                           |
+----+-------------+-------+------+-----------------------------+----------------+---------  +---------------------------+-------+---------------------------------+
|  1 | SIMPLE      | v     | ALL  | secretkey_idx               | NULL           | NULL    | NULL                      |     9 | Using temporary; Using filesort |
|  1 | SIMPLE      | sr    | ref  | idx_subreq_key,cli_date_idx | idx_subreq_key | 103     | crystal_du_sm.v.secretkey | 88746 | Using where                     |
|  1 | SIMPLE      | c     | ref  | idx_cli,cli_type_idx        | idx_cli        | 258         | crystal_du_sm.sr.cli      |     1 | Using where                     |
+----+-------------+-------+------+-----------------------------+----------------+---------   +---------------------------+-------+---------------------------------+
3 rows in set (0.00 sec)

--- 2012 年 8 月 23 日 ---

+----+-------------+-------+------+---------------------------------------+------------  -----+---------+----------------------------+-------+-----------------+
| id | select_type | table | type | possible_keys                         | key               | key_len | ref                        | rows  | Extra           |
+----+-------------+-------+------+---------------------------------------+-----------------+---------+----------------------------+-------+-----------------+
|  1 | SIMPLE      | v     | ALL  | secretkey_idx                         | NULL            | NULL    | NULL                       |     9 | Using temporary |
|  1 | SIMPLE      | sr    | ref  | idx_subreq_key,idx_date_cli_secretkey | idx_subreq_key  | 103     | crystal_du_sm.v.secretkey  | 88608 | Using where     |
|  1 | SIMPLE      | c     | ref  | idx_cli_clitype                       | idx_cli_clitype     | 260     | crystal_du_sm.sr.cli,const |     1 | Using where     |
+----+-------------+-------+------+---------------------------------------+----------------   -+---------+----------------------------+-------+-----------------+
3 rows in set (0.00 sec)
4

1 に答える 1

1

いくつかの一般的な注意事項:

  • 予約済みキーワードを列名として使用しないでください ( subscriptionrequest.date )
  • 特に関数を使用する場合は、フィールド名にエイリアスを使用してください

このバージョンの方が読みやすいと思います

  SELECT DATE(sr.`date`) AS sr_date, v.company_name, c.cli, 
  COUNT(*) AS cnt, c.charge, 
  SUM(c.`charge`) AS charge_sum 
  FROM 
  subscriptionrequest AS sr 
  JOIN cli AS c ON sr.cli = c.cli     
  JOIN vendor AS v ON sr.secretkey = v.secretkey
  WHERE 
  sr.`date` >= '2012-03-12' AND sr.`date` <= '2012-10-13' 
  AND c.clitype = 'chargemo' 
  GROUP BY DATE(sr.`date`), sr.secretkey, c.cli;

おそらく、 subscriptionrequestテーブルを変更する必要があります。

ALTER TABLE subscriptionrequest DROP INDEX `idx_subreq_cli` , DROP INDEX 
`idx_subreq_date`, ADD INDEX `cli_date` (`date`,`cli`);

これにより、日付フィールドに基づいてレコードの適切なサブセットを取得できるため、subscriptionrequestテーブルから返されるレコードの数を減らすことができます。

編集#1

スキーマの変更と (わずかな) クエリの最適化:

ALTER TABLE subscriptionrequest DROP INDEX `cli_date`, 
ADD INDEX `idx_date_cli_secretkey` (`date`,`secretkey`,`cli`);

ALTER TABLE `cli` DROP INDEX idx_cli, DROP INDEX cli_type_idx, 
ADD INDEX `idx_cli_clitype` (cli,clitype);

EXPLAIN  SELECT DATE(sr.`date`) AS sr_date, v.company_name, c.cli, 
COUNT(*) AS cnt, c.charge, SUM(c.`charge`) AS charge_sum    
FROM    subscriptionrequest AS sr JOIN 
cli AS c ON sr.cli = c.cli JOIN vendor AS v ON sr.secretkey = v.secretkey     
WHERE  sr.`date` >= '2012-03-12' AND sr.`date` <= '2012-10-13' 
AND c.clitype = 'chargemo' GROUP BY DATE(sr.`date`), sr.secretkey, c.cli 
ORDER BY NULL\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: sr
         type: index
possible_keys: idx_subreq_key,idx_date_cli_secretkey
          key: idx_date_cli_secretkey
      key_len: 160
          ref: NULL
         rows: 1
        Extra: Using where; Using index; Using temporary
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: c
         type: ref
possible_keys: idx_cli_clitype
          key: idx_cli_clitype
      key_len: 260
          ref: so_12055859.sr.cli,const
         rows: 1
        Extra: Using where
*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: v
         type: ref
possible_keys: secretkey_idx
          key: secretkey_idx
      key_len: 52
          ref: so_12055859.sr.secretkey
         rows: 1
        Extra: Using where
3 rows in set (0.01 sec)
于 2012-08-21T14:26:23.243 に答える