我有一个规格化订单数据的大型数据库,查询报告的速度变得非常慢.我在报告中使用的许多查询连接了五个或六个表,并且必须判断数万或数十万行.

有很多查询,其中大多数都进行了尽可能多的优化,以减少服务器负载并提高速度.我认为现在是开始以非规范化格式保存数据副本的时候了.

有什么办法吗?我是否应该从几个最糟糕的问题开始,然后从那里开始?

推荐答案

我对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.

Database相关问答推荐

Postgres和Oracle之间 Select 查询的结果差异

我如何计算mongo中的多个字段?

在保持抽象的同时将格式化文本存储在数据库中

为什么引用 SQLite rowid 会导致外键不匹配?

用于存储食谱的数据库设计

如果我 for each 用户随机设置 SALT,我如何对他们进行身份验证?

聊天的数据库模式:私有和群组

数据库设计:喜欢表?

Django:如何以线程安全的方式执行 get_or_create()?

如何在sqlite数据库中添加日期

内存数据库和磁盘内存数据库的区别

Neo4j:逐步创建自动索引

如何使用 MySQL Workbench 更改字段的值?

PostgreSQL 字符变长限制

Slick 3.0 在数据库驱动程序级别是reactive/asynchronous的吗?对于哪些数据库?

我是否需要为关系数据库表的主键创建单独的索引

EF4 代码优先导致 InvalidOperationException

我应该在数据库模式中允许空值吗?

如何使用 MySQL Workbench 架构差异两个数据库?

Firebase 排行榜排名