我有一个规格化订单数据的大型数据库,查询报告的速度变得非常慢.我在报告中使用的许多查询连接了五个或六个表,并且必须判断数万或数十万行.
有很多查询,其中大多数都进行了尽可能多的优化,以减少服务器负载并提高速度.我认为现在是开始以非规范化格式保存数据副本的时候了.
有什么办法吗?我是否应该从几个最糟糕的问题开始,然后从那里开始?
我有一个规格化订单数据的大型数据库,查询报告的速度变得非常慢.我在报告中使用的许多查询连接了五个或六个表,并且必须判断数万或数十万行.
有很多查询,其中大多数都进行了尽可能多的优化,以减少服务器负载并提高速度.我认为现在是开始以非规范化格式保存数据副本的时候了.
有什么办法吗?我是否应该从几个最糟糕的问题开始,然后从那里开始?
我对MSSQL的了解比对MySQL的了解更多,但我认为您正在讨论的联接数量或行数不会给正确的索引带来太多问题.您是否分析过查询计划以查看是否遗漏了任何计划?
http://dev.mysql.com/doc/refman/5.0/en/explain.html个
也就是说,一旦您对您的索引感到满意,并且用尽了所有其他方法,反规范化可能是正确的答案.如果您只有一两个查询是有问题的,那么手动方法可能是合适的,而某些类型的数据仓库工具可能更适合创建开发数据立方体的平台.
这是我找到的一个涉及这个主题的网站:
http://www.meansandends.com/mysql-data-warehouse/?link_body%2Fbody=%7Bincl%3AAggregation%7D
这里有一个简单的技术,如果您一次只执行几个查询(我不会替换您的OLTP表,只是出于报告目的创建一个新表),您可以使用它来保持非规范化查询的简单性.假设您的应用程序中有以下查询:
select a.name, b.address from tbla a
join tblb b on b.fk_a_id = a.id where a.id=1
您可以创建一个非规范化的表,并使用几乎相同的查询进行填充:
create table tbl_ab (a_id, a_name, b_address);
-- (types elided)
请注意,下划线与您使用的表别名匹配
insert tbl_ab select a.id, a.name, b.address from tbla a
join tblb b on b.fk_a_id = a.id
-- no where clause because you want everything
然后,要修复应用程序使用新的非规范化表格,请将点切换为下划线.
select a_name as name, b_address as address
from tbl_ab where a_id = 1;
对于大型查询,这可以节省大量时间,明确数据来自何处,并且可以重复使用已有的查询.
记住,我只是在倡导这是最后的手段.我打赌有一些索引会对你有所帮助.在反规范化时,不要忘记考虑磁盘上的额外空间,并确定何时运行查询来填充新表.这可能是在晚上,或者活动量较低的时候.当然,表格中的数据永远不会是最新的.
[又一次编辑]别忘了,您创建的新表也需要编制索引!好处是您可以索引您的核心内容,而不必担心更新锁争用,因为除了大容量插入之外,表将只看到SELECT.