mysql - 在mysql中使用多个连接时加快查询速度

标签 mysql sql

我有一个sql查询,需要连接5个表。到目前为止我已经尝试过这个查询。 它正在工作,但需要很长时间。这里可以做什么来优化以下查询?

$select_query = 'select ';

        $select_query .= "ROUND((
                             6371 * ACOS(
                               COS(RADIANS('.$lat.'))  COS(RADIANS(lat))  COS(
                                 RADIANS(lng) - RADIANS('.$lng.')
                               ) + SIN(RADIANS('.$lat.')) * SIN(RADIANS(lat))
                             )
                           ),2) AS property_distance ,";

        $select_query .= "
                        pro.id as id,
                        pro.user_id,
                        pro.category_id,
                        pro.total_price,
                        pro.size,
                        pro.lat,
                        pro.lng,
                        pro.city,
                        pro.city_english,
                        pro.created_at,
                        pimg.image as property_images,
                        pimg.property_id,
                        pa.property_id,
                        pa.category_attribute_id,
                        pa.is_multiple_data,
                        pa.attribute_value,

                        ca.category_id,
                        ca.attribute_name,
                        ct.category_id,
                        ct.category_name,

                        cat.attribute_id,
                        cat.attribute_label,
                        cat.locale

                     FROM
                        property pro FORCE INDEX (property_index)
                    left join property_images pimg on pro.id=pimg.property_id

                    JOIN property_attributes pa ON
                        pa.property_id = pro.id

                    left JOIN category_attributes ca ON
                        ca.id = pa.category_attribute_id

                    left JOIN category_attributes_translations cat ON
                        ca.id = cat.attribute_id

                    left JOIN categories_translation ct ON
                        pro.category_id = ct.category_id

                    WHERE pro.is_confirm='1' and pro.status='1' and pro.deal_finish='0' and cat.locale='" . $locale . "' and ct.locale='" . $locale . "'

                    GROUP BY pro.id HAVING property_distance<=10 ORDER by pro.id DESC";

然后最后运行这个查询。

请建议我优化此查询的正确方法。

最佳答案

在进行任何连接之前,我会修改查询以遍历属性表并消除尽可能多的行。 HAVING 子句中关于大圆距离计算结果的条件将要求对 WHERE 子句未消除的每一行进行计算。

我会只针对 property 编写一个查询表,类似这样的:

         SELECT ROUND( ( 6371 * ACOS( COS(RADIANS( :lat ) ) 
                                    * COS(RADIANS(pro.lat))
                                    * COS(RADIANS(pro.lng) - RADIANS( :lng ) ) 
                                    + SIN(RADIANS( :lat ))
                                    * SIN(RADIANS(pro.lat))
                                )
                       )
                ,2) AS property_distance
              , pro.id
              , pro.user_id
              , pro.category_id
              , pro.total_price
              , pro.size
              , pro.lat
              , pro.lng
              , pro.city
              , pro.city_english
              , pro.created_at
           FROM property pro
          WHERE pro.is_confirm  = '1' 
            AND pro.status      = '1'
            AND pro.deal_finish = '0'
         HAVING property_distance <= 10
          ORDER
             BY pro.id DESC

这假设 id是唯一的property table 。这应该能够有效利用具有前导列的索引 deal_finish , statusis_confirm以消除某些行的考虑。

   ... ON property (deal_finish,status,is_confirm,...)

一旦我们有了这个集合,我们就可以在外部查询中将其引用为内联 View (派生表),并且外部查询可以与其他表进行联接。

请注意,如果 product_images 中有多个匹配行并在 product_attributes ,对两个表进行联接将创建一个半笛卡尔积,每一行都来自 product_imageproduct_attribute 中的每一行匹配。即 product_image 中的 20 行交叉连接到 product_attribute 中的 20 行将生成一组 400 行。

SELECT c.*
  FROM (  -- inline view query
          SELECT ROUND( ( 6371 * ACOS( COS(RADIANS( :lat ) ) 
                                    * COS(RADIANS(pro.lat))
                                    * COS(RADIANS(pro.lng) - RADIANS( :lng ) ) 
                                    + SIN(RADIANS( :lat ))
                                    * SIN(RADIANS(pro.lat))
                                )
                       )
                ,2) AS property_distance
              , pro.id
              , pro.user_id
              , pro.category_id
              , pro.total_price
              , pro.size
              , pro.lat
              , pro.lng
              , pro.city
              , pro.city_english
              , pro.created_at
           FROM property pro
          WHERE pro.is_confirm  = '1' 
            AND pro.status      = '1'
            AND pro.deal_finish = '0'
         HAVING property_distance <= 10
          ORDER BY pro.id DESC
       ) c

  LEFT
  JOIN product_images pimg 
    ON pimg.product_id = c.id

 ORDER BY c.id DESC

现在出现了使用 GROUP BY 的整个问题。折叠行以及功能上不依赖的表达式、ONLY_FULL_GROUP_BY sql_mode 等行为。

关于mysql - 在mysql中使用多个连接时加快查询速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57420339/

相关文章:

java - 将 BigInteger 存储到 Mysql

php - 无法在分页结果上将数组字段重命名为 FIELDNAME 类型

sql - 多对多关系的单个 SQL 查询

sql - 基于多个条件更新 SQL 表中的单个列

php - 创建url而不是表单操作(例如wordpress slug而不是pageid)

MySQL GROUP By 仅当两列匹配时

php - 通过php获取myisam_sort_buffer_size值?

mysql - Drupal MySQL 查询优化

sql - 查询每个部门最近雇佣的员工

mysql - SQL查询以查找ID在另一列中不存在的位置