mysql优化 - 加入时不使用主键

时间:2018-02-12 19:17:49

标签: mysql query-optimization

我在系统中优化查询时遇到问题。我已经删除了表格描述,留下了相关的字段。我不明白为什么它从基本上扫描巨大的sold_data表开始,但似乎忽略了主键 - 在该表中找到比“mls_id ='FL-REG'”更多的行(1,724,112)值?此查询花费了大量时间。

我刚才注意到的一件事是两个表之间的默认字符集是不同的。希望这不是(一)问题。

CREATE TABLE `FL_REG_IDX_CORE` (
  `mls_id` varchar(20) NOT NULL DEFAULT '',
  `mls_no` varchar(20) NOT NULL DEFAULT '',
  `status` char(1) DEFAULT 'A',
  `address` varchar(80) DEFAULT NULL,
  `city` varchar(40) DEFAULT NULL,
  `state` char(2) DEFAULT NULL,
  `zip` varchar(5) DEFAULT NULL,
  `type` varchar(25) NOT NULL DEFAULT '',
  `price` int(11) unsigned NOT NULL DEFAULT '0',
  `office` varchar(80) DEFAULT NULL,
  `agent` varchar(80) DEFAULT NULL,
  PRIMARY KEY (`mls_id`,`mls_no`),
  KEY `fast_city` (`status`,`city`),
  KEY `agent` (`agent`),
  KEY `office` (`office`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8


ROWS by status:
| status | count(*) |
+--------+----------+
| A      |   26,620 |
| P      |    5,233 |
| S      |  701,762 |


CREATE TABLE `sold_data` (
  `mls_id` varchar(20) NOT NULL DEFAULT '',
  `mls_no` varchar(20) NOT NULL DEFAULT '',
  `sold_price` int(11) unsigned NOT NULL DEFAULT '0',
  `sold_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`mls_id`,`mls_no`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Total Rows: 45,331,566
Rows with mls_id = 'FL-REG': 701,762



explain
SELECT *
FROM FL_REG_IDX_CORE CORE
JOIN sold_data SOLD ON CORE.mls_id = SOLD.mls_id
                AND CORE.mls_no = SOLD.mls_no 
                AND SOLD.mls_id = 'FL-REG'
WHERE ( CORE.mls_id = 'FL-REG' )
AND CORE.status = 'S'
AND CORE.city = 'North Palm Beach'
AND CORE.agent = 'Paul Portugal'

+----+-------------+-------+--------+---------------------------------------------------------+---------+---------+------------+---------+-------------+
| id | select_type | table | type   | possible_keys                                           | key     | key_len | ref        | rows    | Extra       |
+----+-------------+-------+--------+---------------------------------------------------------+---------+---------+------------+---------+-------------+
|  1 | SIMPLE      | SOLD  | ref    | PRIMARY                                                 | PRIMARY | 22      | const      | 1724112 | Using where |
|  1 | SIMPLE      | CORE  | eq_ref | PRIMARY,fast_city,fast_state,fast_type_city_state,agent | PRIMARY | 124     | const,func |       1 | Using where |

1 个答案:

答案 0 :(得分:0)

您注意到CHARACTER SETs不同,回答了您自己的问题。该表的区别是重要; JOIN 中列的差异非常重要。在尝试比较不同CHARACTER SETCOLLATION中的列时,优化程序会引发争议。这导致表扫描而不是使用索引;因此"过多的时间"。

在表的一个上使用ALTER TABLE ... CONVERT TO ...转换为另一个的charset。这将在更改定义的同时正确转换编码。

这些名字闻起来只有美国,所以latin1就足够了。

statusstatezip不应该是utf8;它们应该是ascii(或latin1,因为他们不需要批量或开销utf8。

是的,如果需要,请添加INDEX(mls_no)。仅在测试(mls_id, mls_no)时,现有的mls_no无法使用。

= 'FL-REG'中不应该有ON; ON仅应用于指定表的关联方式。两个表都不需要= 'FL-REG';优化程序将从CORE.mls_id = SOLD.mls_id推断出它。 (本段不影响正确性或表现,只有'样式'。)

要进一步加快查询速度,请将INDEX(status, city)更改为INDEX(status, city, agent)