mysql - 如何使JOIN查询中的ORDER BY更快?我没有尝试过

标签 mysql join sql-order-by query-optimization

我有以下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 (不带 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 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大大降低了速度。

我还在所有3个表上做了一个ANALYZE TABLE,它们都报告了OK。然后,我用LIKE替换了查询中的每个=,它实际上使没有ORDER BY的查询从 0.2秒变为 3秒。换句话说,用LIKE替换=会使原始查询花费的时间与添加ORDER BY一样长!考虑到LIKE=做更多的工作,怎么可能?也许这就是为什么ORDER BY花费这么长时间的线索?

这里是我尝试过的东西(不成功):

1)我没有尝试SELECT table1.*, table2.*而不是SELECT table1.col1,但它仍然花费了 3秒的时间来完成。

2)我尝试在col1中的col2col3col6Table1上添加复合索引,但是它没有提高执行速度。

3)我尝试使用this solution将该查询作为子查询,然后在最后将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使这个顽固的查询快速运行? 还是那不可能?

编辑:

所有3个表的SHOW CREATE TABLE结果:
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。根据this,不应将其设置在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

另一方面,这是IVAN最新查询中EXPLAIN EXTENDED的结果:
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

在另一件事上,这很奇怪。以下带有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

基本上,此版本的查询执行FROM Table3 AS T3JOIN表1和2,而原始查询执行FROM Table1 AS T1JOIN表2和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的原始查询和新查询同时执行filesorttemporary的。 怎么会快10倍?

甚至更陌生的是,切换filesort的顺序似乎也不会改善Ivan的原始查询或较新的查询。 为什么?

最佳答案

好,
我建议您重新设置查询样式:

  • 放在与连接条件不相关的位置,请参阅第二个查询:

    AND(T1.col3 LIKE'X'或T1.col3 LIKE'X-Y')
  • 避免使用IN
  • 避免像那样使用 =

    AND T1.col3 IN('X','X-Y')
  • 避免在
  • 所在的位置进行计算

    创建一些新列以存储:
    SIN(PI() * T3.latitude / 180)
    COS(PI() * table3.longitude / 180 - PI() * 37.1092162 / 180)
    COS(PI() * T3.latitude / 180) 
    
  • 预评估

    SIN(PI()* $ usersLatitude / 180)
    COS(PI()* $ usersLatitude / 180)
  • 如果所有这些“技巧”都无法避免文件排序,则强制索引

  • mysql query index hint

    进一步添加

    为了删除:
    ( T2.Col4 = 'Y' OR T2.Col5 = 'Y' )
    

    在这种情况下,您不能使用 IN ,因此请创建一个新列,该列是该表达式的结果。
    alter table table2 add static1 bit default 0;
    alter table add index idx_static1(static1);
    update table2 t2 set static1=1 where ( T2.Col4 = 'Y' OR T2.Col5 = 'Y' );
    
    alter table table3 add static2 float(18,16) default 0;
    update table3 set static2=SIN(PI() * T3.latitude / 180) where 1
    
    alter table table3 add static3 float(18,16) default 0;
    update table3 set static3 = COS(PI() * T3.latitude / 180) * COS(PI() * table3.longitude / 180 - PI() * 37.1092162 / 180)   where 1
    

    如果 table1.col2 值很少
    alter table table1 change col2 col2 enum('A','B','C');
    

    如果 table1.col3 值很少
    alter table table1 change col3 col3 enum('X','Y','X-Y');
    

    为涉及以下内容的所有列创建唯一索引
    更改表添加索引idx01(col1,col2,col3)
    SELECT STRAIGHT_JOIN
          T1.*, 
          T2.*
       FROM 
          Table1 AS T1
             JOIN Table2 AS T2 ON T1.Col1 = T2.Col1
             JOIN Table3 as T3 ON T1.Col1 = T3.Col1
    
       WHERE static1=1 AND
              T1.Col2 = 'A'
          AND T1.col3 IN ( 'X', 'X-Y') 
          AND T1.Col1 != 1
          AND ACOS(  
                     ( 
                       $usersLatitude_sin_pi_fract180  * t3.static2 
                       + $usersLatitude_cos_pi_fract180  * t3.static3 
                     )   
                   ) <= 0,00252321929476 -- this's 10/3963.191
          ORDER BY T1.Col6
    

    您的评论建议我您在查询中使用了不同的排序规则(col1是latin1_swedish,而col2是utf8),或者您的连接使用了其他排序规则(您的连接是utf-8,并且查询了latin1_german列),因此在查询时:
    t1.col2 = 'A'
    

    Mysql必须将每个值从utf-8转换为latin1。

    另请参见mysql文档的collate section

    一种快速的方法是将所有(列,表,服务器,连接,客户端)转换为相同的排序规则singel字节,如果您不需要utf-8会更好。

    请小心我可能做的类型错误或语法错误。

    进一步添加2

    我在测试数据库上重新创建了表,并修复了以下列:
    t1.col2,t2.col3 不能为空,t1.col1是主要的,不能为null。

    索引“t1.CompositeIndex1”应仅索引:col2,col3,col1;为“order by”列编制索引是不充分的或最糟糕的。

    我创建了static1,并在t2.col1和t2.static1上创建了一个索引,但是我的DB中的6行未使用(请参阅后面的说明)。 t2.static1也不能为空。

    我还将查询调整为各列的排序规则:
    SELECT  T1.*, T2.* 
    FROM Table1 AS T1
             JOIN Table2 AS T2   ON ( T1.Col1 = T2.Col1   )
             JOIN Table3 as T3 ON T1.Col1 = T3.Col1
       WHERE  
             (  T1.Col2 =    'A'   collate utf8_bin  AND T1.col3 IN  ( 'X' collate utf8_bin , 'X-Y'  collate utf8_bin )   AND T1.Col1 != 1 )
    and T2.static1=1
          AND ACOS(  (   2.3  * T3.static2  + 1.2 * T3.static3  ) ) <= 0.00252321929476 
          ORDER BY T1.Col6
    

    下面按照解释扩展
    +----+-------------+-------+--------+-----------------------------------+-----------------+---------+----------------+------+----------+-----------------------------+
    | id | select_type | table | type   | possible_keys                     | key             | key_len | ref            | rows | filtered | Extra                       |
    +----+-------------+-------+--------+-----------------------------------+-----------------+---------+----------------+------+----------+-----------------------------+
    |  1 | SIMPLE      | T1    | ref    | PRIMARY,col2,col3,CompositeIndex1 | CompositeIndex1 | 1       | const          |    1 |   100.00 | Using where; Using filesort |
    |  1 | SIMPLE      | T2    | eq_ref | PRIMARY,CompositeIndex1           | PRIMARY         | 4       | testdb.T1.col1 |    1 |   100.00 | Using where                 |
    |  1 | SIMPLE      | T3    | eq_ref | PRIMARY                           | PRIMARY         | 4       | testdb.T1.col1 |    1 |   100.00 | Using where                 |
    +----+-------------+-------+--------+-----------------------------------+-----------------+---------+----------------+------+----------+-----------------------------+ 
    

    列的是否与相同:select_type,table,type,key,ref,filtered,Extra?

    我的优化目标是:
    -在少数索引中满足where条件
    -避免计算
    -避免整理转换
    -避免或
    -在where条件下避免NULL

    现在的坏消息
    看来在表中您已经有约14万条记录,并且如果查询涉及很多行,则使用顺序查询可能意味着使用文件排序方法,因此最终答案可以按照@mavroprovato的建议增加内存排序缓冲区。

    进一步添加3

    要评估 key_buffer_size 是否足够,请参阅http://dba.stackexchange.com

    进一步添加4

    我认为只有Oracle中的某人可以确切地说出发生了什么,但是我有主意。

    我认为这个查询很奇怪:
  • 所有表(t1,t2,t3)都由主键
  • 连接
  • 其他条件仅取决于calcs(t3.colX)
  • 有些条件仅取决于索引(t1.colX)

  • 因为有1个from_table_rows> = join1_table_rows> = join2_table_rows,所以最快从from表返回的行将是另外2个JOIN

    用于评估工作量的优化器将计算出一个类似的公式:
    effort = num_rows*key_size/index_cardinality
    

    (index_cardinality由phpmyadmin显示在每个索引旁边)

    由于2的努力是> = num_rows

    我的查询
    由于3,table1(来自table)返回92333行,table3(join1_table)减少到1(!)行,table2保留1行(努力〜3)。

    您的查询
    由于2,您应该付出的努力= 140000,但幸运的是calc仅返回1个结果,因此您的查询非常快捷

    演示

    在您的查询从“<= 10”(在联接条件下)更改为“<= 1000”或更多时,您将看到性能呈指数下降。

    在我的查询中,从“<= 10”(在连接条件下)更改为“<= 1000”或更多,您将看到性能的线性/对数下降。

    进一步添加5

    问题的答案:排序缓冲区大小是否太大?

    站在文章上,是的,请尝试一些调整,也许您可​​以解决问题

    问题的答案:不可能快速查询吗?

    恕我直言,这是可能的(即使sort-buffer-size无法解析)。

    我的想法很简单,可以在这种情况下继续进行:“圆弧不错,但方形更好。”

    目前,最大基数在表3中的坐标上,但是由于公式原因,索引不适用。因此,您可以搜索“正方形”内的所有点,而不是搜索半径内的所有点
    FROM table3
    ...
    WHERE (t3.latitude-0.15) < $usersLatitude AND  $usersLatitude < t3.latitude+0.15  
    AND t3.longitue - 0.15 < $usersLongitude AND   $usersLongitude < t3.longitue + 0.15
    

    因此您可以在(t3.latitude,t3.longitue)中创建索引。

    0.15度应为10英里。
    当然,您应该在日变化子午线附近和两极附近修复计算

    如果您严格需要半径,则可以使用半径公式(请参见下面的示例)或重新连接table3(如果可能)执行(/详细说明)公式,直到可以直接将值与列进行比较。
    FROM table3 t3
    JOIN table3 t3bis ON t3.id=t3bis.id
    ...
    WHERE (t3.latitude-0.15) < $usersLatitude AND  $usersLatitude < t3.latitude+0.15  
    AND t3.longitue - 0.15 < $usersLongitude AND   $usersLongitude < t3.longitue + 0.15
    AND 
    3963.191 
    * ACOS(  (SIN(PI() * $usersLatitude / 180) * SIN(PI() * t3bis.latitude / 180)) 
    + (  COS(PI() * $usersLatitude / 180) * COS(PI() * t3bis.latitude / 180) 
    * COS(PI() * t3bis.longitude / 180 - PI() * 37.1092162 / 180)
    )   
    ) <= 10 
    

    再添加6

    主题:编译函数做得更好

    使用RADIANS()函数
    degree * PI / 180 == radians(degree)
    

    使用mysql的GIS扩展

    看到这个article about MySql GIS extension

    关于mysql - 如何使JOIN查询中的ORDER BY更快?我没有尝试过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13569769/

    相关文章:

    php - Laravel 修改 Auth::user() 查询?

    php - ü 等外来字符不要进入 Mysql

    php - Preg_replace 没有正确替换

    php - 使用远程 MySQL 数据库中的用户进行日志记录

    join - couchdb 加入 2 个文档

    php - Laravel/Mysql 分组排序

    MySQL在准备好的语句中检测关键字

    php - Join 函数用于将一个表中的字段值与另一表中的字段值进行匹配

    java - 希望通过hibernate hbm xml映射按降序排序

    sql - 为什么指定 ORDER BY 子句时 SQL Server 会忽略字符串连接中的值