doudiao2335 2013-07-21 23:12
浏览 257

使用多个连接和Group_Concat优化php mySQL查询

I have multiple join sets happening on my query. I have multiple joins, because of the way the tables are structured to get what I want. My main joins, I've separated into three sets as commented below. If I only have one set, the query time is pretty fast. When I have two sets active, the query time is around 2 minutes. If all three sets are active as shown below, it takes too long.

Any help on optimizing this query would be appreciated.

$query  = "SELECT   `Databases`.*, 
                    `DatabaseDescriptors`.*, 
                    `DatabaseContents`.*, 
                    `DatabaseAccessLevels`.*, 
                    `Providers`.*, 
                    GROUP_CONCAT(`Descriptors`.DescriptorName SEPARATOR ', ') as DescriptorNames, 
                    GROUP_CONCAT(`Contents`.ContentName SEPARATOR ', ') as ContentNames, 
                    GROUP_CONCAT(`AccessLevels`.AccessLevelName SEPARATOR ', ') as AccessLevelNames ";

$query .= "FROM `Databases` ";

// SET 1

$query .= "JOIN `DatabaseDescriptors` 
                ON `DatabaseDescriptors`.DatabaseID = `Databases`.DatabaseID ";

$query .= "JOIN `Descriptors` 
                ON `Descriptors`.DescriptorID = `DatabaseDescriptors`.DescriptorID ";

//SET 2

$query .= "JOIN `DatabaseContents`
                ON `DatabaseContents`.DatabaseID = `Databases`.DatabaseID ";

$query .= "JOIN `Contents`
                ON `Contents`.ContentID = `DatabaseContents`.ContentID ";

//SET 3

$query .= "JOIN `DatabaseAccessLevels`
                ON `DatabaseAccessLevels`.DatabaseID = `Databases`.DatabaseID ";

$query .= "JOIN `AccessLevels`
                ON `AccessLevels`.AccessLevelID = `DatabaseAccessLevels`.AccessLevelID ";

$query .= "JOIN `Providers`
                ON `Providers`.ProviderID = `Databases`.ProviderID ";

$query .= "AND `Databases`.DatabaseID = 47";
  • 写回答

1条回答 默认 最新

  • duandao2306 2013-07-22 00:50
    关注

    The reason for the performance problem is that a "database" has multiple descriptors, access levels, and contents. Say a database has 10 of each. The query ends up turning this into 10*10*10 = 1000 rows for processing.

    The solution is to do the aggregation before doing the join. For instance, instead of this: $query .= "JOIN DatabaseDescriptors ON DatabaseDescriptors.DatabaseID = Databases.DatabaseID ";

    $query .= "JOIN `Descriptors` 
                    ON `Descriptors`.DescriptorID = `DatabaseDescriptors`.DescriptorID ";
    

    You would have:

    (select dd.DatabaseId,
             GROUP_CONCAT(d.DescriptorName SEPARATOR ', ') as DescriptorNames
     from DatabaseDescriptors dd join
          Descriptions d
          on dd.DescriptorID = d.DescriptorID
     group by dd.DatabaseId
    ) dd
    on Databases.DatabaseId = dd.DatabaseId
    

    (You can replace the group by dd.DatabaseId with where dd.DatabaseId = 47 to just handle your one case. My guess is that you might want this information for all databases. If so, add a group by DatabaseId to the outer query.)

    You then need to repeat this for all three of the group_concat() columns.

    Note: You are pulling all the fields from the all the tables. However, only one row is returning because you have an aggregation query with no group by. I'm guessing that you are also getting duplicates in the group_concat()-created lists. This approach will also fix that problem.

    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。