【问题标题】:Optimized query with performance measurement (from mysql to) in postgresql在 postgresql 中使用性能测量(从 mysql 到)优化查询
【发布时间】:2013-08-12 01:09:55
【问题描述】:
SELECT m.title , m.run_time FROM movie m WHERE m.run_time < (SELECT AVG (run_time) FROM movie) *1.1 AND m.run_time > (SELECT AVG (run_time) FROM movie) *0.9;

在 postgresql 中花费 4.6 到 8

基本上,它会选择平均运行时间在 10% 以内的电影的标题和运行时间。电影表是这样的:

CREATE TABLE MOVIE
(
title             varchar(40)                             NOT NULL,
production_year        smallint                             NOT NULL,
country         varchar(20)                            NOT NULL,
run_time        smallint                            NOT NULL,
major_genre         varchar(15)                                 ,
CONSTRAINT pk_movie PRIMARY KEY(title,production_year)
);

并且有 101 个条目。

由于“SELECT AVG (run_time) FROM movie”被使用了两次,我想将平均值粘贴到一个变量中,并在第二个查询中引用该变量。 Mysql长这样,运行起来,两个命令的时间总和比上面的参考查询要短。

SET @average = (SELECT AVG (run_time) FROM movie);
SELECT m.title , m.run_time FROM movie m WHERE m.run_time < @average *1.1 AND m.run_time > @average *0.9;

现在,如何在 postgresql 中等效地执行此操作?我在下面列出了我的尝试

当我尝试在 postgresql 中创建变量时,如下所示:

\set average (SELECT AVG (run_time) FROM movie);

这行得通。但下一行:

SELECT m.title , m.run_time FROM movie m WHERE m.run_time < :average *1.1 AND m.run_time > :average *0.9;

ERROR:  syntax error at or near "FROMmovie"
LINE 1: ...OM movie m WHERE m.run_time < (SELECTAVG(run_time)FROMmovie)...

发生,我认为是因为 \set 按字面意思放置我的命令,就像一个字符串变量,并且不像 mysql 那样评估它。

所以我尝试做一个临时表

CREATE TEMP TABLE temptable ( theaverage float );
insert into temptable  ( SELECT AVG (m.run_time) FROM movie m );
SELECT m.title , m.run_time FROM movie m WHERE m.run_time < (Select * from temptable) *1.1 AND m.run_time > (Select * from temptable) *0.9;

这些工作。但是(测量)性能不太好。

explain analyze CREATE TEMP TABLE temptable ( theaverage float ); //cannot analyze this/does not work/syntax error happens.
ERROR:  syntax error at or near "float"
LINE 1: ...in analyze CREATE TEMP TABLE temptable ( theaverage float );

explain insert into temptable  ( SELECT AVG (m.run_time) FROM movie m ); //costs 2.3ish

explain SELECT m.title , m.run_time FROM movie m WHERE m.run_time < (Select theaverage from temptable) *1.1 AND m.run_time > (Select theaverage from temptable) *0.9;

//成本 63 到 66,什么?这将使其成本大大高于未优化的查询,即 4.6 到 8。

我也尝试过 SELECT INTO,但我不知道如何正确使用它来达到我的目的。

那么,我再重复一遍这个问题,如何制作一个优化版本的

"SELECT m.title , m.run_time FROM movie m WHERE m.run_time < (SELECT AVG (run_time) FROM movie) *1.1 AND m.run_time > (SELECT AVG (run_time) FROM movie) *0.9;"

也许通过在 postgresql 中使用变量和性能测量?

【问题讨论】:

    标签: mysql sql database postgresql optimization


    【解决方案1】:

    此解决方案不使用变量,适用于 PostgreSQL 和 MySQL:

    SELECT m.title, m.run_time
    FROM movie m, 
        (SELECT avg(run_time) AS time FROM movie) a
    WHERE m.run_time BETWEEN a.time * 0.9
                         AND a.time * 1.1
    

    必填SQLFiddle

    请注意,在列 run_time 上添加索引应该会提高此查询的性能(假设您的 movies 表很大):

    CREATE INDEX movies_run_time_idx ON movies(run_time);
    

    【讨论】:

    • 谢谢,我尝试在我的数据库上运行它,在 postgresql 中查询的成本为 2.3-6.8,低于原始查询。
    猜你喜欢
    • 2021-12-06
    • 1970-01-01
    • 2022-07-26
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多