我有以下 JOIN 查询:
SELECT
table1.*,
table2.*
FROM
Table1 AS table1
LEFT JOIN
Table2 AS table2
USING
(col1)
LEFT JOIN
Table3 as table3
USING
(col1)
WHERE
3963.191 *
ACOS(
(SIN(PI() * $usersLatitude / 180) * SIN(PI() * table3.latitude / 180))
+
(COS(PI() * $usersLatitude / 180) * COS(PI() * table3.latitude / 180) * COS(PI() * table3.longitude / 180 - PI() * 37.1092162 / 180))
) <= 10
AND
table1.col1 != '1'
AND
table1.col2 LIKE 'A'
AND
(table1.col3 LIKE 'X' OR table1.col3 LIKE 'X-Y')
AND
(table2.col4 = 'Y' OR table2.col5 = 'Y')
// Data Types of all columns in the query:
// col1: int(11)
// col2: char(1)
// col3: varchar(3)
// col4: char(1)
// col5: char(1)
// col6: int(11)
// latitude: varchar(25)
// longitude: varchar(25)
// All 3 tables (table1, table2, and table3) are `MyISAM`.
它在0.15 秒内执行。
但是,如果我简单地添加:
ORDER BY
table1.col6 DESC
它执行超过3 秒。
查询中的所有列都被索引,包括table1.col6
在ORDER BY
.
以下是EXPLAIN EXTENDED
WITHOUT ORDER BY
的结果:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE table1 ALL PRIMARY,col2,col3 NULL NULL NULL 140101 72.61 Using where
1 SIMPLE table2 eq_ref PRIMARY,col4,col5 PRIMARY 4 table1.col1 1 100 Using where
1 SIMPLE table3 eq_ref PRIMARY PRIMARY 4 table1.col1 1 100 Using where
这是EXPLAIN EXTENDED
WITH ORDER BY
的结果:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE table1 ALL PRIMARY,col2,col3 NULL NULL NULL 140101 72.61 Using where; Using filesort
1 SIMPLE table2 eq_ref PRIMARY,col4,col5 PRIMARY 4 table1.col1 1 100 Using where
1 SIMPLE table3 eq_ref PRIMARY PRIMARY 4 table1.col1 1 100 Using where
奇怪的是,我ORDER BY DESC
在此站点上的其他几个查询中使用它,它并没有像使用这个特定查询那样减慢它的速度。这个查询有一些特定的东西导致它随着ORDER BY
.
我也在ANALYZE TABLE
所有 3 张桌子上做了一个,他们都报告了OK
。LIKE
然后我将查询中的every 替换为=
它实际上使查询没有ORDER BY
从0.2 seconds变为3 seconds。换句话说,替换LIKE
为=
使原始查询花费与添加一样长ORDER BY
的时间!这怎么可能,考虑到LIKE
做更多的工作比=
?也许这就是为什么ORDER BY
需要这么长时间的线索?
这是我迄今为止尝试过的(不成功):
1) 而不是SELECT table1.*, table2.*
,我只是尝试了SELECT table1.col1
,但仍然需要3 多秒才能完成。
2) 我尝试在、、和in上添加复合索引,但并没有提高执行速度。col1
col2
col3
col6
Table1
3)我尝试了将查询作为子查询然后在最后包装外部的解决方案ORDER BY
,但它并没有提高执行速度。
4)我尝试了以下版本的查询,但它没有改进任何东西,并且实际上使查询花费了3 秒以上,甚至没有ORDER BY
添加到它(也许这提供了另一个线索):
SELECT STRAIGHT_JOIN
T1.*,
T2.*
FROM
Table1 AS T1
JOIN Table2 AS T2
ON T1.Col1 = T2.Col1
AND ( T2.Col4 = 'Y' OR T2.Col5 = 'Y' )
JOIN Table3 as T3
ON T1.Col1 = T3.Col1
AND 3963.191
* ACOS( (SIN(PI() * $usersLatitude / 180) * SIN(PI() * T3.latitude / 180))
+ ( COS(PI() * $usersLatitude / 180) * COS(PI() * T3.latitude / 180)
* COS(PI() * table3.longitude / 180 - PI() * 37.1092162 / 180)
)
) <= 10
WHERE
T1.Col2 LIKE 'A'
AND ( T1.col3 LIKE 'X' OR T1.col3 LIKE 'X-Y')
AND T1.Col1 != '1'
ORDER BY
T1.Col6
// With the following composite indexes:
// On Table 1, index on ( Col2, Col3, Col1, Col6 )
// On Table 2, index on ( Col1, Col4, Col5 )
// Remember, all individual columns are already indexed.
...
我怎样才能让这个顽固的查询快速运行ORDER BY
? 或者那是不可能的?
编辑:
SHOW CREATE TABLE
所有 3 个表的结果:
CREATE TABLE `Table1` (
`col1` int(11) unsigned NOT NULL AUTO_INCREMENT,
`col100` varchar(25) CHARACTER SET utf8 DEFAULT NULL,
`col101` varchar(60) COLLATE utf8_bin DEFAULT NULL,
`col102` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
`col103` varchar(10) COLLATE utf8_bin DEFAULT '00000000',
`col104` date NOT NULL,
`col105` int(3) DEFAULT NULL,
`col106` varchar(25) COLLATE utf8_bin DEFAULT NULL,
`col107` varchar(20) COLLATE utf8_bin DEFAULT 'Blah',
`col108` varchar(2) COLLATE utf8_bin DEFAULT 'No',
`col109` varchar(15) COLLATE utf8_bin DEFAULT 'Blah',
`col2` enum('A','B') COLLATE utf8_bin DEFAULT NULL,
`col3` enum('A','B','A-B') COLLATE utf8_bin DEFAULT NULL,
`col110` decimal(10,7) NOT NULL DEFAULT '0.0000000',
`col111` decimal(10,7) NOT NULL DEFAULT '0.0000000',
`col112` char(1) COLLATE utf8_bin DEFAULT 'N',
`col113` char(1) COLLATE utf8_bin DEFAULT 'N',
`col114` int(11) DEFAULT NULL,
`col115` varchar(15) COLLATE utf8_bin DEFAULT 'Blah',
`col6` int(11) DEFAULT NULL,
`col117` varchar(45) COLLATE utf8_bin DEFAULT NULL,
`col118` varchar(2) COLLATE utf8_bin NOT NULL,
`col119` tinyint(2) NOT NULL,
`col120` int(6) NOT NULL,
`col121` varchar(7) COLLATE utf8_bin NOT NULL,
`col122` varchar(6) COLLATE utf8_bin NOT NULL,
`col123` char(1) COLLATE utf8_bin NOT NULL DEFAULT 'A',
`col124` varchar(200) COLLATE utf8_bin NOT NULL,
`col125` tinyint(4) NOT NULL,
`col126` tinyint(1) NOT NULL,
`col127` varchar(1) COLLATE utf8_bin NOT NULL DEFAULT 'A',
`col128` tinyint(1) NOT NULL DEFAULT '0',
`col129` smallint(5) unsigned NOT NULL,
`col130` varchar(1) COLLATE utf8_bin NOT NULL DEFAULT 'A',
`col131` int(11) NOT NULL,
`col132` tinyint(1) NOT NULL,
`col133` tinyint(1) NOT NULL,
`col134` varchar(1) COLLATE utf8_bin NOT NULL,
`col135` varchar(200) COLLATE utf8_bin NOT NULL,
`col136` int(11) NOT NULL,
`col137` int(10) unsigned NOT NULL,
`col138` int(11) NOT NULL,
`col139` tinyint(1) NOT NULL,
`col140` tinyint(1) NOT NULL,
`col141` tinyint(4) NOT NULL,
`col142` varchar(25) COLLATE utf8_bin NOT NULL,
`col143` varchar(25) COLLATE utf8_bin NOT NULL,
`col144` tinyint(1) unsigned NOT NULL,
`col145` tinyint(4) NOT NULL,
PRIMARY KEY (`col1`),
KEY `col2` (`col2`),
KEY `col3` (`col3`),
KEY `CompositeIndex0` (`col1`,`col2`,`col3`,`col6`),
KEY `CompositeIndex1` (`col2`,`col3`,`col1`,`col6`),
KEY `idx01` (`col1`,`col2`,`col3`)
[19 other indexes that do not involve col1, col2, col3, or col6...]
) ENGINE=MyISAM AUTO_INCREMENT=160640 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
//*******************************************************//
CREATE TABLE `Table2` (
`col1` int(11) unsigned NOT NULL DEFAULT '0',
`col201` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'Blah',
`col202` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'Blah',
`col203` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col204` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col205` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col206` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col207` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col208` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col209` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col210` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col211` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col212` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col213` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col214` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col215` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col216` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col217` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col218` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col219` varchar(45) COLLATE utf8_bin DEFAULT 'Blah',
`col220` varchar(255) COLLATE utf8_bin DEFAULT 'Blah',
`col221` varchar(255) COLLATE utf8_bin DEFAULT 'Blah',
`col222` varchar(255) COLLATE utf8_bin DEFAULT 'Blah',
`col223` varchar(255) COLLATE utf8_bin DEFAULT 'Blah',
`col224` varchar(45) COLLATE utf8_bin DEFAULT ‘Blah’,
`col225` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`col4` char(1) COLLATE utf8_bin DEFAULT 'A',
`col226` char(1) COLLATE utf8_bin DEFAULT 'A',
`col227` varchar(5) COLLATE utf8_bin DEFAULT 'Blah',
`col228` char(1) COLLATE utf8_bin NOT NULL,
`col229` text COLLATE utf8_bin,
`col5` char(1) COLLATE utf8_bin DEFAULT 'A',
`col230` varchar(255) COLLATE utf8_bin DEFAULT 'Blah',
`col231` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`col232` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`col233` varchar(255) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`col1`),
KEY `col4` (`col4`),
KEY `col5` (`col5`),
KEY `CompositeIndex1` (`col1`,`col4`,`col5`),
[4 other indexes not involving col1, col4, col5...]
FULLTEXT KEY `col220` (`col220`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin
//*******************************************************//
CREATE TABLE `Table3` (
`col1` int(11) unsigned NOT NULL DEFAULT '0',
`col300` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`latitude` varchar(25) COLLATE utf8_bin NOT NULL DEFAULT '0',
`longitude` varchar(25) COLLATE utf8_bin NOT NULL DEFAULT '0',
`col301` int(11) DEFAULT NULL,
`static2` float(18,16) DEFAULT '0.0000000000000000',
`static3` float(18,16) DEFAULT '0.0000000000000000',
PRIMARY KEY (`col1`),
KEY `latitude` (`latitude`),
KEY `longitude` (`longitude`),
KEY `static2` (`static2`),
KEY `static3` (`static3`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin
编辑2:
下面是我的MySQL 配置文件。除其他事项外,请注意如何sort-buffer-size
设置为1M
. 据此,它不应该设置在上面,256K
否则它实际上可以减慢“37x”的速度。 这可能是问题的一部分吗?
# The MySQL database server configuration file.
[mysqld]
open-files-limit = 20000
thread-cache-size = 16
table-open-cache = 2048
table-definition-cache = 512
query-cache-type = 1
query-cache-size = 32M
query-cache-limit = 1M
sort-buffer-size = 1M
read-buffer-size = 1M
read-rnd-buffer-size = 8M
join-buffer-size = 1M
tmp-table-size = 64M
max-heap-table-size = 64M
back-log = 100
max-connections = 200
max-connect-errors = 10000
max-allowed-packet = 16M
interactive-timeout = 600
wait-timeout = 180
net_read_timeout = 30
net_write_timeout = 30
back_log = 128
myisam-sort-buffer-size = 128M
innodb-buffer-pool-size = 320M
innodb-log-buffer-size = 4M
innodb-log-file-size = 128M
innodb-log-files-in-group = 2
innodb-file-per-table = 1
[mysqldump]
max-allowed-packet = 16M
在另一件事上,以下是EXPLAIN EXTENDED
来自 IVAN 的最新查询的结果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE T1 ref PRIMARY,col2,col3,col1,CompositeIndex1,idx01 CompositeIndex1 2 const 92333 Using where; Using filesort
1 SIMPLE T3 eq_ref PRIMARY PRIMARY 4 T1.col1 1 Using where
1 SIMPLE T2 eq_ref PRIMARY,CompositeIndex1,idx_static1 PRIMARY 4 T1.col1 1 Using where
在另一件事上,这里有一些非常奇怪的东西。以下版本的 WITH 查询ORDER BY
只需0.2 秒即可完成:
SELECT STRAIGHT_JOIN T1 . * , T2 . *
FROM Table3 AS T3
JOIN Table2 AS T2 ON T3.col1 = T2.col1
AND (
T2.col4 = 'Y'
OR T2.col5 = 'Y'
)
JOIN Table1 AS T1 ON T3.col1 = T1.col1
AND 3963.191 * ACOS( (
SIN( PI( ) * - 87.8819594 /180 ) * SIN( PI( ) * T3.latitude /180 ) ) + ( COS( PI( ) * - 87.8819594 /180 ) * COS( PI( ) * T3.latitude /180 ) * COS( PI( ) * T3.longitude /180 - PI( )* 37.1092162 /180 ) )
) <=10
WHERE T1.col2 LIKE 'A'
AND (
T1.col3 LIKE 'X'
OR T1.col3 LIKE 'X-Y'
)
AND T1.col1 != '1'
ORDER BY T1.col6 DESC
基本上,这个版本的查询执行 aFROM Table3 AS T3
和JOIN
表 1 和 2,而原始查询执行的是表 2FROM Table1 AS T1
和JOIN
3。
这是EXPLAIN EXTENDED
上面的查询:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE T3 ALL PRIMARY NULL NULL NULL 141923 100 Using where; Using temporary; Using filesort
1 SIMPLE T2 eq_ref PRIMARY,col4,col5,CompositeIndex1 PRIMARY 4 T3.col1 1 100 Using where
1 SIMPLE T1 eq_ref PRIMARY,col2,col3,col1,CompositeIndex1,idx01 PRIMARY 4 T2.col1 1 100 Using where
注意这个查询实际上是如何对来自 Ivan 的原始查询和新查询 同时执行 afilesort
和 a temporary
vs. 的。怎么能快 10 倍?filesort
更奇怪的是,切换顺序JOIN
似乎并没有改善原始查询和来自 Ivan 的新查询。 这是为什么?