0

以下は、約8秒かかるクエリの結果であり、使用可能なインデックスがありますが、使用されていません。レコードは40,000しかありません。

mysql> SELECT * FROM (`phppos_customers`) 
   JOIN `phppos_people` ON `phppos_customers`.`person_id`=`phppos_people`.`person_id`
   WHERE `deleted` = 0 ORDER BY `last_name` asc LIMIT 20
    -> ;
** PERSONAL DATA REMOVED **

mysql> EXPLAIN SELECT * FROM (`phppos_customers`) JOIN `phppos_people` ON `phppos_customers`.`person_id`=`phppos_people`.`person_id` WHERE `deleted` = 0 ORDER BY `last_name` asc LIMIT 20
    -> ;
+----+-------------+------------------+--------+-------------------+---------+---------+--------------------------------+-------+---------------------------------+
| id | select_type | table            | type   | possible_keys     | key     | key_len | ref                            | rows  | Extra                           |
+----+-------------+------------------+--------+-------------------+---------+---------+--------------------------------+-------+---------------------------------+
|  1 | SIMPLE      | phppos_customers | ref    | person_id,deleted | deleted | 4       | const                          | 22545 | Using temporary; Using filesort |
|  1 | SIMPLE      | phppos_people    | eq_ref | PRIMARY           | PRIMARY | 4       | pos.phppos_customers.person_id |     1 |                                 |
+----+-------------+------------------+--------+-------------------+---------+---------+--------------------------------+-------+---------------------------------+
2 rows in set (0.00 sec)

mysql> describe phppos_customers;
+----------------+--------------+------+-----+---------+-------+
| Field          | Type         | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| person_id      | int(10)      | NO   | MUL | NULL    |       |
| account_number | varchar(255) | YES  | UNI | NULL    |       |
| company_name   | varchar(255) | NO   |     | NULL    |       |
| taxable        | int(1)       | NO   |     | 1       |       |
| deleted        | int(1)       | NO   | MUL | 0       |       |
+----------------+--------------+------+-----+---------+-------+
5 rows in set (0.01 sec)

mysql> describe phppos_people;
+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| first_name   | varchar(255) | NO   | MUL | NULL    |                |
| last_name    | varchar(255) | NO   | MUL | NULL    |                |
| phone_number | varchar(255) | NO   |     | NULL    |                |
| email        | varchar(255) | NO   | MUL | NULL    |                |
| address_1    | varchar(255) | NO   |     | NULL    |                |
| address_2    | varchar(255) | NO   |     | NULL    |                |
| city         | varchar(255) | NO   |     | NULL    |                |
| state        | varchar(255) | NO   |     | NULL    |                |
| zip          | varchar(255) | NO   |     | NULL    |                |
| country      | varchar(255) | NO   |     | NULL    |                |
| comments     | text         | NO   |     | NULL    |                |
| person_id    | int(10)      | NO   | PRI | NULL    | auto_increment |
+--------------+--------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)

編集:show create table phppos_customers;

| phppos_customers | CREATE TABLE `phppos_customers` (
  `person_id` int(10) NOT NULL,
  `account_number` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `company_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `taxable` int(1) NOT NULL DEFAULT '1',
  `deleted` int(1) NOT NULL DEFAULT '0',
  UNIQUE KEY `account_number` (`account_number`),
  KEY `person_id` (`person_id`),
  KEY `deleted` (`deleted`),
  CONSTRAINT `phppos_customers_ibfk_1` FOREIGN KEY (`person_id`) REFERENCES `phppos_people` (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |

編集:show create table phppos_people;

| phppos_people | CREATE TABLE `phppos_people` (
  `first_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `last_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `phone_number` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `address_1` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `address_2` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `city` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `state` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `zip` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `country` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `comments` text COLLATE utf8_unicode_ci NOT NULL,
  `person_id` int(10) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`person_id`),
  KEY `first_name` (`first_name`),
  KEY `last_name` (`last_name`),
  KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=45870 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |

ショーインデックスの編集:

mysql> show index from phppos_customers;
+------------------+------------+----------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+
| Table            | Non_unique | Key_name       | Seq_in_index | Column_name    | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------------+------------+----------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+
| phppos_customers |          0 | account_number |            1 | account_number | A         |           2 |     NULL | NULL   | YES  | BTREE      |         |
| phppos_customers |          1 | person_id      |            1 | person_id      | A         |       46217 |     NULL | NULL   |      | BTREE      |         |
| phppos_customers |          1 | deleted        |            1 | deleted        | A         |           2 |     NULL | NULL   |      | BTREE      |         |
+------------------+------------+----------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set (0.00 sec)

mysql> show index from phppos_people;
+---------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table         | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| phppos_people |          0 | PRIMARY    |            1 | person_id   | A         |       45699 |     NULL | NULL   |      | BTREE      |         |
| phppos_people |          1 | first_name |            1 | first_name  | A         |       45699 |     NULL | NULL   |      | BTREE      |         |
| phppos_people |          1 | last_name  |            1 | last_name   | A         |       45699 |     NULL | NULL   |      | BTREE      |         |
| phppos_people |          1 | email      |            1 | email       | A         |       45699 |     NULL | NULL   |      | BTREE      |         |
+---------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
4 rows in set (0.04 sec)
4

1 に答える 1

1

Explainの出力を見ると、これはmysqlが現在行っていることです。

  1. テーブルから開始しphppos_customers、インデックスを使用して次のdeleted行を検索しますdeleted = 0
  2. すべての行(残り22k)phppos_peopleについて、同じperson_id(参加)の情報を検索します。
  3. すべてを一時テーブルに入れlast_name、インデックスなしで並べ替えると、既に結合された結果セットであるため、並べ替えに役立ちます。最初の20を見つけるには、すべての行を並べ替える必要があります。

何らかの理由でオプティマイザが間違った結合順序を選択したため、これはこのクエリを実行するための最適な方法のようには見えません。

STRAIGHT_JOINを使用して、異なる結合順序を強制してみてください。

SELECT * FROM `phppos_people` STRAIGHT_JOIN `phppos_customers` 
  ON `phppos_customers`.`person_id`=`phppos_people`.`person_id` 
WHERE `deleted` = 0 
ORDER BY `last_name` ASC LIMIT 20;

今回、mysqlは次のことを行う必要があります。

  1. その列のインデックスを使用してphppos_peopleソートすることから始めます。last_name
  2. すべての行について結合phppos_customersし、かどうかを確認しますdeleted = 0
  3. 制限の最適化を使用し、最初に20を見つけたら停止します。
于 2012-06-18T01:11:01.670 に答える