【问题标题】:sql, query optimisation with and inner join?sql,查询优化和内部连接?
【发布时间】:2012-03-16 04:48:41
【问题描述】:

我正在尝试优化我的查询,它有一个内部连接和合并。

连接表,是一个包含一个整数字段的简单表,我添加了一个唯一键。

对于我的 where 子句,我为三个字段创建了一个键。

但是当我查看计划时,它仍然说它正在使用表扫描。

我哪里错了?

这是我的查询

select date(a.startdate, '+'||(b.n*a.interval)||' '||a.intervaltype) as due

from billsndeposits a 

inner join util_nums b on date(a.startdate, '+'||(b.n*a.interval)||' 
     '||a.intervaltype) <= coalesce(a.enddate, date('2013-02-26')) 

where not (intervaltype = 'once' or interval = 0) and factid = 1 

order by due, pid;

【问题讨论】:

  • 我认为这是mysql,对吧?
  • 请提供您正在使用的数据库的名称。您可能还有其他选择。
  • date(a.startdate, '+'||(b.n*a.interval)||' '||a.intervaltype) 这行得通吗?
  • 不,不是 mySql,是 sqlite
  • @Jordan 是的,它确实有效

标签: sql join query-optimization


【解决方案1】:

您的 JOIN 表达式很可能不能使用任何索引,它是通过执行 NATURAL 扫描并为每一行计算 date(a.startdate, '+'||(b.n*a.interval)||' '||a.intervaltype) 来计算的。

顺便说一句:这本身就是一个非常奇怪的连接条件。我建议你找到一个更好的方法来加入billsndeposits 到util_nums(如果确实需要的话)。

【讨论】:

  • 好吧,我在 intervaltype 字段中存储天数、月数等,并添加一个由间隔生成的数字并评估它以生成自定义日期重复。 util_nums 纯粹是为了在将来提供重复。例如'+ 7 个月'
  • @Jules 我无法真正理解您要实现的目标以及两个表的结构和内容是什么,也许您可​​以通过包含表结构和示例来更新您的问题内容加上你想要达到的目标的描述。
【解决方案2】:

我想我理解你想要达到的目标。但是这种连接会导致性能下降。即使您删除日期计算和合并(即将一个日期与另一个日期进行比较),即使使用索引,它仍然会很慢(与整数连接相比)。而且因为您正在动态创建新日期,所以无法为它们编制索引。

我建议创建一个包含 2 列 (1) pid(或您在 billsndeposits 中使用的任何 id)和 (2)recurrence_dt 的临时表

使用此查询填充新表:

INSERT INTO TEMP
SELECT PID, date(a.startdate, '+'||(b.n*a.interval)||' '||a.intervaltype)
FROM billsndeposits a, util_numbs b;

然后在recurrence_dt 列和runstats 上创建索引。现在您的 select 语句可能如下所示:

SELECT recurrence_dt
FROM temp t, billsndeposits a
WHERE t.pid = a.pid
  AND recurrence_dt <= coalesce(a.enddate, date('2013-02-26'))

你可以在这个新表上添加一个exp_ts,然后让临时数据过期。

我知道这会为您的原始查询增加更多工作量,但这是有保证的性能改进,并且应该自然地适合经常运行的脚本。

问候,

编辑

我会做的另一件事是让 enddate 默认值 = date('2013-02-26'),除非它会影响其他代码和/或没有商业意义。这样您就不必使用合并。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 2018-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    相关资源
    最近更新 更多