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