【问题标题】:How To Compute the Cost of Querying an Additional Table Using LEFT JOIN?如何计算使用 LEFT JOIN 查询附加表的成本?
【发布时间】:2014-01-30 18:13:58
【问题描述】:

我的任务是估计在用 SQL 编写的 PostgreSQL 数据库报告查询中加入一个附加表的边际成本。我得到了一个测试程序来测试查询的性能。无论是否填充连接表,运行时间之间似乎没有统计学上的显着差异。如何编写更好的测试来说明两种场景之间查询时间的差异?

在每种情况下,SQL 都是相同的,将表 A 与表 B 连接起来。唯一的区别是表 B 是否包含任何数据。

表 A 有这些列:

    Column    |            Type             
--------------+-----------------------------
 sid          | bigint                      
 cluster      | text                         
 sn           | text                        
 tag_id       | integer                      
 src_ip       | text                         
 dst_ip       | text                         
 dst_port     | integer                      
 protocol     | text                         
 src_intf     | text                         
 dst_intf     | text                         
 disp         | smallint                     
 rcvd_bytes   | bigint                       
 sent_bytes   | bigint                       
 duration     | integer                      
 count        | integer                      
 start_time   | timestamp without time zone  
 policy_id    | text                         
 src_user     | text                         
 dst_domain   | text                         
 app_id       | text                         
 signature_id | text                         
 deny_type_id | text                         
 reputation   | text                         
 wb_cat_id    | text                         
 alarm_name   | text                         
 virus        | text                         
 sender       | text                         
 recipients   | text                         
 host         | text                         
 dlp_rule_id  | text                         
 spam_type    | text                         
 spam_action  | text                         

表 B 有这些列:

    Column    |            Type             
--------------+-----------------------------
 appliance_id | integer                      
 ip           | inet                         
 fqdn         | text                         
 resolve_time | timestamp without time zone  
 expire_time  | timestamp without time zone  

这两个表由 inet 类型的 IPv4 地址连接。

测试数据在表 A 和 B 中分别填充了 500 多行数据。

填充表 B 后,运行查询的测试程序平均需要 18.216 秒的总时间来运行。运行之间的标准差为 1.143 秒。

在表 B 为空的情况下,运行查询的测试程序平均需要 18.523 秒的总时间来运行。运行之间的标准差为 1.928 秒。

每种情况下的样本量为六次。我怀疑我需要使用更大的样本量,但不确定合适的样本量是多少。

【问题讨论】:

  • 第一个表中没有inet列,那它是如何连接的呢?而且每行加入 500 行需要 18 秒,这非常慢,肯定有更复杂的事情发生。 PostgreSQL 中是否有可能获取这些查询的实际 CPU/IO 使用情况并将它们也包括在比较中?
  • 表 A 较旧,应该使用 inet,但使用文本作为 IP 地址。报告测试程序首先使用一组已知数据填充表 A,然后运行报告。我可能需要从测试程序中删除一些代码,如果结果证明这些代码没有用,对测量查询执行时间的目标没有贡献。
  • 如果表格那么小(500 行),那么使用正确的类型(将 inet 类型连接到输入文本是一个很好的选择......)和正确的表格结构,这样的查询应该在10 毫秒左右。
  • 我使用集成测试来运行查询,但后来切换到通过 shell 脚本传递给 psql 的手工 SQL 查询。我生成了额外的数据,将表 A 的大小增加了六倍,达到大约 3000 行。表 B 保持在 500 行。我看到了更合理的结果:填充表 B 的平均 23.586 秒和空表 B 的 19.431 秒(21% 开销)。我进行了 10 次运行,每次 100 次迭代,无论是否填充了表 B。

标签: sql performance postgresql join estimation


【解决方案1】:

我使用 LEFT JOIN 编写了一个简单的查询:

SELECT * FROM a
         LEFT JOIN b
                   ON a.src_ip::inet = b.ip
                   AND b.resolve_time IS NOT NULL AND b.resolve_time <= now()
                   AND b.expire_time IS NOT NULL AND now() < b.expire_time

然后我运行了 10 次测试,每次测试 100 次迭代(查询),并对每次测试运行的结果进行计时。

结果如下:

通过平均运行时间并计算填充了表 B 的运行时间与未填充表 B 的运行时间的比率,我能够计算出使用表 B 的查询相对于没有填充表 B 的查询的开销为 21.38%。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-26
    • 2022-01-20
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多