【发布时间】: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