我在系统中优化查询时遇到问题。我已经删除了表格描述,留下了相关的字段。我不明白为什么它从基本上扫描巨大的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 |
答案 0 :(得分:0)
您注意到CHARACTER SETs
不同,回答了您自己的问题。该表的区别是不重要; JOIN
中列的差异非常重要。在尝试比较不同CHARACTER SET
或COLLATION
中的列时,优化程序会引发争议。这导致表扫描而不是使用索引;因此"过多的时间"。
在表的一个上使用ALTER TABLE ... CONVERT TO ...
转换为另一个的charset。这将在更改定义的同时正确转换编码。
这些名字闻起来只有美国,所以latin1就足够了。
status
,state
,zip
不应该是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)
。