首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加快对日期部分位于不同列的表的select查询

加快对日期部分位于不同列的表的select查询
EN

Stack Overflow用户
提问于 2019-02-23 08:33:52
回答 3查看 101关注 0票数 0

运行以下查询需要很长时间。

logins表有10M条记录,并且有一个关于月、日和年的索引。可以做些什么来加快查询速度?

代码语言:javascript
复制
SELECT
cast(logins.month || '/' || logins.day || '/' || logins.year as date) as loginDt, logins.person
FROM logins
LEFT JOIN MIN_LUNCH
    ON MIN_LUNCH.person = logins.person
    AND MIN_LUNCH.date = cast(logins.month || '/' || logins.day || '/' || logins.year as date)
WHERE
    cast(logins.month || '/' || logins.day || '/' || logins.year as date) between '01/01/2010' and '03/01/2010'
EN

回答 3

Stack Overflow用户

发布于 2019-02-23 08:47:05

要修复查询,必须修改表结构。考虑使用BIGINT列存储unix-timestamp或DATE列。这将使查询数据库变得更容易、更快。

更改结构后,您的查询可能如下所示:

代码语言:javascript
复制
SELECT
  from_unixtime(logins.login_date, '%m-%d') as loginDt, 
  logins.person
FROM 
  logins
  LEFT JOIN MIN_LUNCH ON MIN_LUNCH.person = logins.person AND MIN_LUNCH.date = logins.date
WHERE 
  logins.date between 1262332800 and 1267430400;
票数 0
EN

Stack Overflow用户

发布于 2019-02-23 08:52:53

对于您提供的日期间隔,应该可以简化WHERE子句:

代码语言:javascript
复制
WHERE logins.month IN (1, 2, 3) AND logins.year = 2010

查询的这一部分应该能够使用现有的索引,但是仍然需要使用JOIN条件,其中需要将date数据类型与包含日期部分的三列相匹配:

代码语言:javascript
复制
MIN_LUNCH.date = cast(logins.month || '/' || logins.day || '/' || logins.year as date)

在这里,对于每条记录,RDBMS都需要执行强制转换操作;这会破坏现有的索引。

出于这个原因以及使用SQL数据类型的原因,我建议您修复数据库结构,并在logins表中将日期存储为dates。

您可以简单地添加一个新列,并从现有数据填充它:

代码语言:javascript
复制
ALTER TABLE logins ADD login_date DATE; -- or the relevant date datatype for your RDBMS
UPDATE logins SET login_date =
    CAST(logins.month || '/' || logins.day || '/' || logins.year as date);

从那时起,您可以在两个表之间使用简单的连接。查询应从以下索引中受益:

代码语言:javascript
复制
logins(person, login_date)
min_lunch(person, date)
票数 0
EN

Stack Overflow用户

发布于 2019-02-23 09:22:30

假设您不能更改表,我认为您可以通过使用日期部分将登录表限制为指定的日期范围来提高查询速度,这样至少您不会对表中的每一行执行这种强制转换,并且您的索引也不会完全无用。

代码语言:javascript
复制
SELECT
  loginRange.loginDt, loginRange.person
FROM
  (SELECT
    cast(logins.month || '/' || logins.day || '/' || logins.year as date) as loginDt, logins.person 
    FROM logins
    WHERE logins.month IN ('01','02','03') AND logins.year = '2010') as loginRange
  LEFT JOIN MIN_LUNCH ON
     MIN_LUNCH.person = logins.person
     AND MIN_LUNCH.date = loginRange.loginDt

显然,如果表使用了正确的数据类型,那么它就不会像预期的那样好,如果您可以修改表,那么就应该对其进行修复。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54837007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档