Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
减少SQL中的获取时间(已完成索引)_Sql_Postgresql_Postgresql Performance - Fatal编程技术网

减少SQL中的获取时间(已完成索引)

减少SQL中的获取时间(已完成索引),sql,postgresql,postgresql-performance,Sql,Postgresql,Postgresql Performance,我有一个有几百万行的表,其中的行经常被插入,甚至更经常被获取 行插入的时间并不重要,但获取的时间是因为它是为网站服务的。所以我, 查询非常简单,不包含任何JOINs 问题发生在SELECT查询中。一旦用户执行搜索,同样的SELECT查询将每隔几秒钟运行一次,以检查新的或更新的行。但是,SELECT查询第一次运行50秒,之后这些查询不到1秒,这并不奇怪 这使我认为问题不在于SELECT语句本身,而在于其他方面 表格如下: CREATE TABLE all_legs (

我有一个有几百万行的表,其中的行经常被插入,甚至更经常被获取

行插入的时间并不重要,但获取的时间是因为它是为网站服务的。所以我,

查询非常简单,不包含任何
JOIN
s

问题发生在
SELECT
查询中。一旦用户执行搜索,同样的
SELECT
查询将每隔几秒钟运行一次,以检查新的或更新的行。但是,
SELECT
查询第一次运行50秒,之后这些查询不到1秒,这并不奇怪

这使我认为问题不在于
SELECT
语句本身,而在于其他方面

表格如下:

CREATE TABLE all_legs (
                carrier TEXT,
                dep_hub TEXT,
                arr_hub TEXT,
                dep_dt TIMESTAMP WITH TIME ZONE,
                arr_dt TIMESTAMP WITH TIME ZONE,
                price_ct INTEGER,
                ... 5 more cols ...,
                PRIMARY KEY (carrier, dep_hub, arr_hub, dep_dt, arr_dt, ...3 other cols...)
                )
索引为:

CREATE INDEX IF NOT EXISTS fetch_index ON all_legs(dep_dt, LEFT(dep_hub::text, 6), LEFT(arr_hub::text, 6));
选择查询:

SELECT * FROM all_legs
                    WHERE dep_dt >= %s
                    AND dep_dt < %s
                    AND (LEFT(dep_hub::text, 6) = %s AND LEFT(arr_hub::text, 6) = %s)

为什么第一次查询要慢得多,如何减少第一次查询的运行时间

查询和索引中的
LEFT
函数可能增加了不必要的复杂性;您可以将通配符匹配与
LIKE
语句一起使用,以获得相同的结果

SELECT * FROM all_legs
WHERE dep_dt >= '2018-01-19'
AND dep_dt < '2018-01-20'
AND dep_hub LIKE 'ES-PMI%'
AND arr_hub LIKE 'ES-MAD%'
从所有支腿中选择*
其中dep_dt>=“2018-01-19”
和部门dt<'2018-01-20'
还有像“ES-PMI%”这样的dep_中心
还有arr_hub像“ES-MAD%”
在最后两个参数的末尾添加一个
%


这样,您还应该能够通过删除包含
LEFT
函数的索引来加快查询速度,并正常索引列。

查询和索引中的
LEFT
函数可能会增加不必要的复杂性;您可以将通配符匹配与
LIKE
语句一起使用,以获得相同的结果

SELECT * FROM all_legs
WHERE dep_dt >= '2018-01-19'
AND dep_dt < '2018-01-20'
AND dep_hub LIKE 'ES-PMI%'
AND arr_hub LIKE 'ES-MAD%'
从所有支腿中选择*
其中dep_dt>=“2018-01-19”
和部门dt<'2018-01-20'
还有像“ES-PMI%”这样的dep_中心
还有arr_hub像“ES-MAD%”
在最后两个参数的末尾添加一个
%

这样,您还应该能够通过删除包含
LEFT
函数的索引来加快查询速度,并正常地对列进行索引。

  • 挤出单个列的示例代码(
    dep\u hub
  • 如果您的{dep_hub,arr_hub}都引用同一个域,那么您必须稍微改变一下
  • 还必须重新定义主键
  • 并且[可能]在挤出表上添加一些函数索引

  • 挤出单个列的示例代码(
    dep\u hub
  • 如果您的{dep_hub,arr_hub}都引用同一个域,那么您必须稍微改变一下
  • 还必须重新定义主键
  • 并且[可能]在挤出表上添加一些函数索引


我的意思是,我将多次运行同一查询,因为我正在检查是否有新的或更新的行。因此,我第一次运行一个新的查询需要很长时间,下面的时间是可以的。我更新了问题以澄清它。无论是谁投票支持close,如果您能解释一下为什么……第一次运行查询需要更长的时间是很常见的。最常见的原因是表或索引中必要的数据块不会缓存在内存中(Linux缓存或pg共享缓冲区中),必须首先从磁盘读取。重复查询时,大多数数据块都已缓存,因此磁盘IO非常小或没有。
carrier TEXT、dep\u hub TEXT、arr\u hub TEXT、
为什么这些PK列都是文本字段?他们的身份是什么?您能否将它们压缩到单独的表中,并通过代理键引用这些表?要使第一个查询更快,您需要在启动期间填充缓存。您可以通过简单地对该表运行一个虚拟查询或使用extensionI来实现这一点。我将多次运行相同的查询,因为我正在检查是否有新的或更新的行。因此,我第一次运行一个新的查询需要很长时间,下面的时间是可以的。我更新了问题以澄清它。无论是谁投票支持close,如果您能解释一下为什么……第一次运行查询需要更长的时间是很常见的。最常见的原因是表或索引中必要的数据块不会缓存在内存中(Linux缓存或pg共享缓冲区中),必须首先从磁盘读取。重复查询时,大多数数据块都已缓存,因此磁盘IO非常小或没有。
carrier TEXT、dep\u hub TEXT、arr\u hub TEXT、
为什么这些PK列都是文本字段?他们的身份是什么?您能否将它们压缩到单独的表中,并通过代理键引用这些表?要使第一个查询更快,您需要在启动期间填充缓存。您可以通过简单地对表运行虚拟查询或使用ExtensionAnks来实现这一点!我可以放下整个表,重新创建它。这会简化事情吗?dep_hub和arr_hub将引用相同的域更好的策略是:就地进行转换,然后重命名表,并通过
select创建新表。。。从旧表
(省略xxx\u hub字段),将PK和FK放在上面,最后删除旧表。(并且:可能用视图替换它,加入xxx_hub表两次…)谢谢!我可以放下整个表,重新创建它。这会简化事情吗?dep_hub和arr_hub将引用相同的域更好的策略是:就地进行转换,然后重命名表,并通过
select创建新表。。。从旧表
(省略xxx\u hub字段),将PK和FK放在上面,最后删除旧表。(和:可能替换为视图,连接xxx_hub表两次…)
    -- [empty] table to contain the "squeezed out" domain
CREATE TABLE dep_hub
    ( id SERIAL NOT NULL PRIMARY KEY
    ,  dep_hub varchar
    , UNIQUE (dep_hub)
    );

   -- This is done in the chained insert/update
-- INSERT INTO dep_hub(dep_hub)
-- SELECT DISTINCT dep_hub
-- FROM all_legs ;


    -- an index may speedup the final update
    -- (the index will be dropped automatically
    -- once the column is dropped)
CREATE INDEX ON all_legs (dep_hub);

    -- The original table needs a "link" to the new table
ALTER TABLE all_legs
    ADD column dep_hub_id INTEGER -- NOT NULL
    REFERENCES dep_hub(id)
    ;

    -- FK constraints are helped a lot by a supportive index.
CREATE INDEX all_legs_dep_hub_fk ON all_legs (dep_hub_id);

    -- Chained query to:
    -- * populate the domain table
    -- * initialize the FK column in the original table
WITH src AS (
    INSERT INTO dep_hub(dep_hub)
    SELECT DISTINCT a.dep_hub
    FROM all_legs a
    RETURNING *
    )
UPDATE all_legs dst
SET  dep_hub_id = src.id
FROM src
WHERE src.dep_hub = dst.dep_hub
    ;

    -- Now that we have the FK pointing to the new table,
    -- we can drop the redundant column.
ALTER TABLE all_legs DROP COLUMN dep_hub;