我有一个连接两个表的查询:
data
中有一个时间戳列orders
具有开始和结束时间戳记列在表1上,timestamp列上有一个索引,在表2上,start | end上有一个索引(按此顺序)。当我像FROM d JOIN o ON d.timestamp > o.start_ts AND d.timestamp <= o.end_ts
问题在于,当订单未完成时,end_ts
为空,因此我需要将联接更改为d.timestamp <= COALESCE(o.end_ts, null)
,从说明中我可以看到现在索引扫描包括一个{ {1}}部分,使其变慢(从1s到14s)。
我当前正在使用的查询是:
filter
解释是
SELECT *
FROM data pd
JOIN orders o ON pd.timestamp > o.start_time AND pd.timestamp <= COALESCE(o.end_time, now())
WHERE pd.machine_id = 19 AND pd.name = 'somevalue' AND pd.timestamp > '2019-09-15 22:00:00' AND pd.timestamp <= '2019-09-22 21:59:59.999'
答案 0 :(得分:2)
这是range types派上用场的情况之一,因为它们正确地处理了NULL值。
在范围内创建索引:
CREATE INDEX orders_range ON orders using gist (tsrange(start_time,end_time,'(]'));
然后在联接条件中使用相同的范围定义
SELECT *
FROM data pd
JOIN orders o ON pd.timestamp <@ ts_range(o.start_time, o.end_time, '(]')
WHERE pd.machine_id = 19
AND pd.name = 'somevalue'
AND pd.timestamp > '2019-09-15 22:00:00' AND pd.timestamp <= '2019-09-22 21:59:59.999'
不相关,但是:我将使用pd.timestamp < '2019-09-22 22:00:00'
而不是<=
运算符,其时间戳是22:00:00之前的几毫秒
答案 1 :(得分:1)
通过使用class Display extends Component {
state = {
bulbs: 3496,
display: []
}
componentDidMount () {
this.createDisplay()
}
createDisplay = () => {
const displayBoard = []
for (let i = 0; i < this.state.bulbs; i++) {
displayBoard.push(
<Light
key={i}
addColor={ this.props.addColor }
color ={ this.props.color }
/>
)
}
this.setState({display: displayBoard})
}
,可以避免对NULL的特殊处理。 (但NOT(negated_condition)
解决方案更干净,IMO)
Infinity
答案 2 :(得分:0)
感谢IRC上的incognito
,我找到了一个可行的解决方案,创建一个像这样的索引:
CREATE INDEX orders_timestamps ON orders (start_time,coalesce(end_time,'infinity'));
,然后将查询更改为pd.timestamp <= COALESCE(o.end_time, 'infinity')
。
这样,我仍然拥有可以为空的值,并且可以使用索引值,因为我无法为NOW()
编制索引,因为它是变量