mariadb不优化'left join'的执行顺序

z9smfwbn  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(117)

对于mariadb-server-10.3.9数据库,表'log_api'中大约有500,000行。
如果将SQL写成普通left join SQL,则需要1.44s:

SELECT a.id,
       a.client_ip,
       a.api_address,
       a.deleted,
       a.create_date,
       a.update_staff,
       a.update_date,
       a.remark,
       a.timestamp,
       a.instance,
       a.msg_data,
       c.project_name,
       d.service_name AS fw_server_name,
       e.agent_name
FROM log_api a
         LEFT JOIN wb_project c ON c.project_code = a.project_code
         LEFT JOIN fw_service d on d.service_code = a.service_code
         LEFT JOIN wb_agent e ON e.agent_code = a.agent_code
where a.deleted = 0
  and timestamp >= '2023-06-05T00:00:00'
  and timestamp
    < '2023-06-07T00:00:00'
order by timestamp desc
limit 100 offset 10000;

但如果sql写为嵌入查询sql,则只需要0.02s:

select m.id,
       m.client_ip,
       m.api_address,
       m.deleted,
       m.create_staff,
       m.update_staff,
       m.update_date,
       m.remark,
       m.timestamp,
       m.instance,
       m.msg_data,
       c.project_name,
       d.service_name AS fw_server_name,
       e.agent_name
from (SELECT a.id,
             a.custom_service_order_code,
             a.service_code,
             a.project_code,
             a.agent_code,
             a.user_name,
             a.client_ip,
             a.api_address,
             a.deleted,
             a.create_staff,
             a.create_date,
             a.update_date,
             a.remark,
             a.timestamp,
             a.instance,
             a.msg_data
      FROM log_api a
      where a.deleted = 0
        and timestamp >= '2023-06-05T00:00:00'
        and timestamp
          < '2023-06-07T00:00:00'
      order by timestamp desc
      limit 100 offset 10000) m
         LEFT JOIN wb_project c ON c.project_code = m.project_code
         LEFT JOIN fw_service d on d.service_code = m.service_code
         LEFT JOIN wb_agent e ON e.agent_code = m.agent_code

几乎所有的SQL性能调优指南都建议避免嵌入查询SQL,因为数据库引擎将有更多的变化来优化普通SQL。有没有人可以确认这是mariadb中的一个bug,或者我使用的是太旧的mariadb版本?

dly7yett

dly7yett1#

SELECT whatever FROM something-complex ORDER BY col LIMIT n是一个臭名昭著的查询性能反模式。为什么?
它必须创建一个中间结果集来执行JOIN,对它进行排序,然后丢弃所有结果集,只剩下一小部分。更糟糕的是,有一个很大的偏移:它必须遍历排序的结果集,丢弃所有的OFFSET行,然后才能返回微小的结果集。
您的第二个示例查询速度更快,因为它只需要在一个表上执行这些操作。而且,它可能更快,因为在ORDER BY子句中使用的timestamp列上有一个索引。(您没有向我们显示表定义。)

相关问题