我们有很多复杂的函数会根据传递的JSON过滤器设置返回列表。问题是,即使一个标志被设置为false,MySQL也会在SELECT语句中执行SQL(使用EXPLAIN)。我不知道如何解决这个问题。例如:
WITH cte1 AS
(
SELECT pm.ID
FROM person_main pm
),
cte2 AS
(
SELECT IF
(
@p_filter_job_state_array IS NULL,
(
SELECT NULL
),
(
SELECT sis.ID
FROM cte1 sis
INNER JOIN external_link el ON el.ref_id = sis.ID
WHERE el.headline_value LIKE '%test%'
)
) AS ID
)
SELECT * FROM cte2;
即使@p_filter_job_state_array为NULL,引擎仍在执行SELECT连接external_link。我们有几十个“前端加载”CTE执行此操作,随着过滤器数量的增长,即使我们没有设置过滤器,执行时间也是原来的两倍和三倍(因为引擎正在执行SELECT语句,而我以为它会根据NULL值忽略这些语句)。我需要弄清楚如何使用CTE编写单个查询,并指示编译器避免基于变量设置执行CTE SELECT语句......这可能吗?如果可能,我该怎么做?
另一个重要的例子是因为我们做了大量的前置加载和过滤,有时调用者只想要一个索引数组而不是整个结构,所以我们有这样的东西:
SELECT IF
(
p_array_only,
(
SELECT JSON_ARRAYAGG(jm.ID)
FROM
(
SELECT fs.ID
FROM final_sort fs
LIMIT var_offset, var_rowcount
) jm
),
(
SELECT JSON_OBJECT
(
'data',
(
SELECT JSON_ARRAYAGG(JSON_OBJECT
(
'data_main', get_json_data_main_list(jm.ID)
))
FROM
(
SELECT fs.ID
FROM final_sort fs
LIMIT var_offset, var_rowcount
) jm
)
)
)
)
当然,问题是如果他们只需要数组,MySQL仍然执行代码的其他部分。是的,我可以把它分成两个单独的SQL语句,但它们使用100%相同的代码“前加载”,所以效率很低。但这是主要问题;我们有一组非常特殊的过滤器需要处理,但我们也需要跳过过滤器,并专注于基于变量设置输出不同的结构。
1条答案
按热度按时间bvjxkvbb1#
不幸的是,社区没有任何React;预处理语句可能是最好的解决方案(而且工作良好),但正如许多人所知,它将管理复杂代码变成了意大利面条,这可能会非常令人沮丧。