Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.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_Ruby On Rails_Ruby_Optimization - Fatal编程技术网

是否可以进一步优化这些SQL查询?

是否可以进一步优化这些SQL查询?,sql,ruby-on-rails,ruby,optimization,Sql,Ruby On Rails,Ruby,Optimization,我有一个Rails应用程序(运行在Heroku帐户上),它正在为主页获取一系列关于符合某些标准的记录数量的统计数据。每个计数在页面上显示为一个数字。我的表(列表)由大约22500条记录组成。在生产环境中,加载页面大约需要350毫秒(仍然低于阈值,但对于主页来说不是很好) 请注意这里的查询数量,我想描述一下我试图做的事情的冗余性。这感觉可以做得更有效率。有什么想法吗 SELECT COUNT(1) FROM listings WHERE (city in ('Syracuse')) SELECT

我有一个Rails应用程序(运行在Heroku帐户上),它正在为主页获取一系列关于符合某些标准的记录数量的统计数据。每个计数在页面上显示为一个数字。我的表(列表)由大约22500条记录组成。在生产环境中,加载页面大约需要350毫秒(仍然低于阈值,但对于主页来说不是很好)

请注意这里的查询数量,我想描述一下我试图做的事情的冗余性。这感觉可以做得更有效率。有什么想法吗

SELECT COUNT(1) FROM listings WHERE (city in ('Syracuse'))
SELECT COUNT(1) FROM listings WHERE (city in ('Syracuse')) AND (created_at >= '2011-01-30 18:28:44.656702')
SELECT COUNT(1) FROM listings WHERE (city in ('Cicero', 'Clay', 'Lysander', 'VanBuren', 'Salina'))
SELECT COUNT(1) FROM listings WHERE (city in ('Cicero', 'Clay', 'Lysander', 'VanBuren', 'Salina')) AND (created_at >= '2011-01-30 18:28:44.811090')
SELECT COUNT(1) FROM listings WHERE (city in ('DeWitt', 'Manlius', 'Pompey'))
SELECT COUNT(1) FROM listings WHERE (city in ('DeWitt', 'Manlius', 'Pompey')) AND (created_at >= '2011-01-30 18:28:44.954442')
SELECT COUNT(1) FROM listings WHERE (city in ('Onondaga', 'Elbridge', 'Geddes', 'Camillus'))
SELECT COUNT(1) FROM listings WHERE (city in ('Onondaga', 'Elbridge', 'Geddes', 'Camillus')) AND (created_at >= '2011-01-30 18:28:45.105438')
SELECT COUNT(1) FROM listings WHERE (city in ('Fabius', 'Lafayette', 'Marcellus', 'Otisco', 'Skaneateles', 'Spafford', 'Tully'))
SELECT COUNT(1) FROM listings WHERE (city in ('Fabius', 'Lafayette', 'Marcellus', 'Otisco', 'Skaneateles', 'Spafford', 'Tully')) AND (created_at >= '2011-01-30 18:28:45.258860')
SELECT COUNT(1) FROM listings WHERE (city in ('West Monroe', 'Hastings', 'Constantia', 'Palermo', 'Mexico', 'Parish', 'Schroeppel'))
SELECT COUNT(1) FROM listings WHERE (city in ('West Monroe', 'Hastings', 'Constantia', 'Palermo', 'Mexico', 'Parish', 'Schroeppel')) AND (created_at >= '2011-01-30 18:28:45.411138') 
我考虑的一个选项是在我的列表模型上使用after_add和after_remove钩子,用这些统计信息更新一个单独的表。我唯一关心的是涉及的维护问题。然而,一天中只会添加几次新列表,所以更新表本身不会导致性能问题


谢谢

各种方法,但并非都面向数据库

您可以将所有选择组合到一个查询中,如下所示:

SELECT COUNT(CASE WHEN city = 'Syracuse' THEN 1 END) as syracuse,
       COUNT(CASE WHEN city = 'Syracuse' AND created_at >= '2011-01-30 18:28:44.656702' THEN 1 END) as syracuse_recent,
       /* etc... */
FROM listings
这将只是对表进行一次扫描,以收集所有统计数据


或者/另外,将从数据库提取的统计数据缓存在应用程序的内存中,或者使用类似memcached的东西。如果不需要统计数据最新的准确性,那么在初始填充之后,这将完全从数据库中卸载查询。

各种方法,而不是所有面向数据库的方法

您可以将所有选择组合到一个查询中,如下所示:

SELECT COUNT(CASE WHEN city = 'Syracuse' THEN 1 END) as syracuse,
       COUNT(CASE WHEN city = 'Syracuse' AND created_at >= '2011-01-30 18:28:44.656702' THEN 1 END) as syracuse_recent,
       /* etc... */
FROM listings
这将只是对表进行一次扫描,以收集所有统计数据


或者/另外,将从数据库提取的统计数据缓存在应用程序的内存中,或者使用类似memcached的东西。如果统计数据不需要最新的准确性,那么在初始填充之后,这将完全从数据库中卸载查询。

首先,您应该检查表上有哪些索引(尝试添加和删除单个字段上的索引以及两个方向上的复合索引)

还要确保准确分析350ms的组成(使用firebug或类似YSlow的东西)


最后,如果您确实有很少的更新,并且希望维护摘要表,那么钩子并不是唯一的方法—您还可以编写触发器来完成这项工作。

首先,您应该检查表上有哪些索引(尝试在各个字段上添加和删除索引,以及在两个方向上添加和删除复合索引)

还要确保准确分析350ms的组成(使用firebug或类似YSlow的东西)


最后,如果您真的有很少的更新,并且希望维护摘要表,那么挂钩并不是唯一的方法—您还可以编写触发器来完成这项工作。

我个人会添加两个新表,一个包含城市组,另一个是组和城市之间的多对多链接表。您需要“城市组id”、“城市组名称”、“dt计数阈值”。第二个表格是“城市组id”、“城市id”。然后可以对多对多链接表执行选择,并使用日期/时间限制加入城市表

-- unrestricted count
selec cg.city_group_name, count(*) as cnt
from dbo.city_group cg
join dbo.city_group_city cgc on cg.city_group_id = cgc.city_group_id
group by city_group_name

-- restricted
selec cg.city_group_name, count(*) as cnt
from dbo.city_group cg
join dbo.city_group_city cgc on cg.city_group_id = cgc.city_group_id
join dbo.city c on c.city_id = cgc.city_id
group by city_group_name
where c.created_at >= cg.dt_count_threshold

请记住,这些是未经测试的查询,因此可能需要进行一些小的调整。并确保所有索引都正确设置,以避免表扫描。

我个人会添加两个新表,一个包含城市组,另一个是组和城市之间的多对多链接表。您需要“城市组id”、“城市组名称”、“dt计数阈值”。第二个表格是“城市组id”、“城市id”。然后可以对多对多链接表执行选择,并使用日期/时间限制加入城市表

-- unrestricted count
selec cg.city_group_name, count(*) as cnt
from dbo.city_group cg
join dbo.city_group_city cgc on cg.city_group_id = cgc.city_group_id
group by city_group_name

-- restricted
selec cg.city_group_name, count(*) as cnt
from dbo.city_group cg
join dbo.city_group_city cgc on cg.city_group_id = cgc.city_group_id
join dbo.city c on c.city_id = cgc.city_id
group by city_group_name
where c.created_at >= cg.dt_count_threshold

请记住,这些是未经测试的查询,因此可能需要进行一些小的调整。并确保所有索引设置正确,以避免表扫描。

默认情况下,它使用的是Heroku提供的Postgres数据库。我也在使用免费的Heroku帐户(可能是罪魁祸首?),它默认使用Heroku提供的Postgres数据库。我也在使用免费的Heroku帐户(可能是罪魁祸首?)。不需要输入我的答案,但我打算提出两个查询,一个带有日期过滤条件,另一个没有。如果所有的查询最终都将覆盖所有的表(这似乎是有可能的),那么使用一个索引不太可能有好处。特别是在PostgreSQL中,它必须引用堆数据。谢谢你的回答。对于CASE语句,这是否开始变得有点过于数据库诺斯替派了?CASE语句是否能跨所有数据库工作?这种语法肯定能在PostgreSQL、SQL Server和Oracle上工作;CASE是ANSI标准构造,用于替换更多特定于db的函数,如
decode()
nullif()
等。像这样使用
sum/count(CASE…
)是一种广泛使用的技术。无需输入我的答案,但我打算建议两个查询,一个带日期过滤条件,另一个不带日期过滤条件。如果所有的查询最终都将覆盖所有的表(这似乎是有可能的),那么使用一个索引不太可能有好处。特别是在PostgreSQL中,它必须引用堆数据。谢谢你的回答。对于CASE语句,这是否开始变得有点过于数据库诺斯替派了?CASE语句是否能跨所有数据库工作?这种语法肯定能在PostgreSQL、SQL Server和Oracle上工作;CASE是ANSI标准构造,用于替换更多特定于db的函数,如
decode()
nullif()
等。像这样使用
sum/count(CASE…
是一种广泛使用的技术。