如何加快这个缓慢的查询

时间:2018-08-31 08:17:38

标签: mysql sql performance explain

我设计了一个mysql数据库,并加载了一些数据(总共可能有10个mio行)。 我正在尝试从时间间隔重叠的两个表中获取数据。

constructor(props) {
    super(props);
    this.state = {
        error: {
            firstName: false
        },
        general: {
            adminFirstName: "",
        },
    };
}
setData = () => {
    const {general} = this.state;
    const isValid = Object.keys(general)
        .filter( key => general[key].length !== 0 ).length === Object.keys(general).length;
    if (!isValid) { 
        Object.keys(general).map(key => { 
            if (general[key].length === 0) { this.setError(key); } });
    } else {
        // this.props.setGeneralData(general);
        // this.props.nextStep();
    }
    console.log(isValid);
    console.log(general);
};
setError = key => {
    const { error } = this.state;
    console.log(key);
    switch (key) {
    case "adminFirstName": {
        this.setState({ error: { ...error, firstName: true } });
    }
    default:
        this.setState({ error: { ...error } });
    }
};
render() {
    const { error, general } = this.state;
    return (
        <div className="block--part_75">
            <Form>
            {/* First name */}
                <Form.Field required error={error.firstName}>
                    <label>First name</label>
                    <Input onChange={e => {
                        e.target.value.length !== 0 
                            ? this.setState({ 
                                error: { ...error, firstName: false },
                                general: {
                                    ...general,
                                    adminFirstName: e.target.value
                                }
                            })
                            : this.setState({
                                error: { ...error, firstName: true },
                                general: {
                                    ...general,
                                    adminFirstName: e.target.value
                                }
                            });
                        }}
                    placeholder="First name"
                    type="text"
                    />
                </Form.Field>
            {/* First name */}
            </Form>
            <Button onClick={this.setData} floated="right">
                Next
            </Button>
        </div>
    );
}

不幸的是,查询花费的时间太长(我还没有完成)。

使用SELECT cd.ParameterID, intervals.TimeStamp, intervals.GreenHouseID, intervals.TargetParam, intervals.ProductionID FROM ( SELECT pd.TimeStamp, p.GreenHouseID, pd.ParameterID AS TargetParam, pd.ProductionID FROM Production p INNER JOIN ProductionData pd ON pd.ProductionID=p.ID GROUP BY pd.TimeStamp, p.GreenHouseID ) AS intervals, ClimateData cd WHERE DATE_FORMAT(intervals.TimeStamp,'%Y-%m-%d') = DATE_FORMAT(cd.Time_stamp,'%Y-%m-%d') AND cd.GreenHouseID = intervals.GreenHouseID GROUP BY intervals.ProductionID, intervals.TargetParam 时,我得到以下结果:

EXPLAIN

我相信我在所有相关列上都添加了索引,以确保快速查询。但是,我设计的查询使用临时表(|id|select_type|table |partitions|type |possible_keys|key |key_len|ref |rows|filtered|Extra |1|PRIMARY |<derived2>|NULL |ALL |NULL |NULL |NULL |NULL | 416| 100.00|Using where Using temporary |1|PRIMARY |cd |NULL |ref |cd_ghid_idx |cd_ghid_idx |4 |intervals.GreenHouseID|1660| 100.00|Using where |2|DERIVED |p |NULL |index|PRIMARY |pr_gh_fk_idx |5 |NULL | 13| 100.00|Using index Using temporary |2|DERIVED |pd |NULL |ref |pd_pr_fk_idx |pd_pr_fk_idx |5 |ghdb.p.ID | 32| 100.00|NULL )。这会降低性能吗?如果是这样,如何设计一个更快的查询?

mysql服务器在我的笔记本电脑上(16GB RAM,CPU E3-1505M v5)。我没有对mysql设置进行任何更改。这样有用吗?

我希望在适当的时间内得到查询结果(几分钟内就可以了)。

谢谢。

1 个答案:

答案 0 :(得分:1)

  • 请为每个表(包括临时表)提供SHOW CREATE TABLE
  • 临时表上似乎有一个单列索引?
  • 温度与永久性应该在性能上没有区别。但是,创建临时表的额外步骤可能会造成费用。
  • 在适当的地方说NOT NULL
  • 在函数调用中隐藏一列(在您的情况下为DATE_FORMAT)可防止使用索引,因此无法使用ALL
  • 您无法“摆脱性能问题”,因此除询问innodb_buffer_pool_size的值外,我将不做其他调整。
  • 请不要使用“逗号联接”;而是使用JOIN .. ON ..

主要性能问题在这里:

WHERE DATE_FORMAT(intervals.TimeStamp,'%Y-%m-%d') = 
      DATE_FORMAT(cd.Time_stamp,'%Y-%m-%d')
  AND cd.GreenHouseID = intervals.GreenHouseID

它看起来应该更像

WHERE intervals.TimeStamp ...
  AND cd.GreenHouseID = intervals.GreenHouseID

由于您要即时构建intervals,因此请创建一列仅包含日期的列。您也可以通过DATE(...)而不是DATE_FORMAT(...)进行计算。

由于您正在计算日期之一,因此将pd.TimeStamp更改为

    DATE(pd.TimeStamp) AS TS_Date

然后

WHERE intervals.TimeStamp >= cd.TS_Date
  AND intervals.TimeStamp  < cd.TS_Date + INTERVAL 1 DAY
  AND intervals.GreenHouseID = cd.GreenHouseID

您还需要与intervals上的此“复合”索引:

INDEX(GreenHouseID, TimeStamp) -- in this order

剩余的错误:我看到GROUP BY pd.TimeStamp, ...;这没有意义,所以我忽略了它。