简体   繁体   English

过滤MySQL结果的最佳实践

[英]Best practice for filtering MySQL results

I want to implement a filter-function in my PHP project. 我想在我的PHP项目中实现一个filter-function。 To implement a filter, I usually just add a WHERE clause in my query to show filtered results. 为了实现过滤器,我通常只在查询中添加一个WHERE子句来显示过滤结果。

My Problem is: These filters require not only a smple added WHERE clause, but a huge Query including multiple JOINs. 我的问题是:这些过滤器不仅需要添加一个简单的WHERE子句,还需要一个包含多个JOIN的巨大查询。 The resulting Query has > 30 lines. 生成的查询有> 30行。

Later, there should also be a search function which would then also require this huge query. 之后,还应该有一个搜索功能,这也需要这个巨大的查询。 I wonder if this is a good practice or if I should add a "redundant" Database column to my database table where I compute the attribute I need for filtering on every update. 我想知道这是一个好习惯还是我应该在我的数据库表中添加一个“冗余”数据库列,在那里我计算每次更新时需要的属性。 With this column, I wouldnt have my huge query on different places over my project, but have a redundant column. 在这个专栏中,我不会在我的项目中对不同的地方进行大量查询,但是有一个冗余列。

What do you think? 你怎么看?

Greetings 问候

As questioned, here the table structure/code. 如有疑问,这里是表结构/代码。 This is not the exact code, because there is also a revision system which makes it even more complex, but for understanding this is enough: 这不是确切的代码,因为还有一个修订系统使它更复杂,但是为了理解这个就足够了:

table submissions: 表提交:

ID (primary)
(additionalColumns)

table reports: 表格报告:

ID (primary)
submissionID (reference to submission table)
(additionalColumns)

table report_objects: table report_objects:

reportID (reference to reports table, multiple report_object for one report)

table accounting: 表会计:

ID (primary)
reportID (reference to reports table, multiple accountings for one report)
(additionalColumns)

table accounting_objects: table accounting_objects:

ID
accountingID (reference to accounting table, multiple accounting_object for one accounting)
(additionalColumns)

For a submission, one or multiple reports are being create with multiple objects to account (report_objects). 对于提交,正在创建一个或多个报告,其中包含多个要记录的对象(r​​eport_objects)。 For each report, I can create multiple accountings, where each accounting is for a few objects of the report. 对于每个报告,我可以创建多个帐户,其中每个帐户用于报告的一些对象。 The accounted report_objects are stored in accounting_object 已记帐的report_object存储在accounting_object中

My query/filter checks, if each report_object of a submissionID is accounted (accounting_object exists) for one submissionID. 我的查询/过滤器检查是否对一个submissionID计入了submissionID的每个report_object(accounting_object存在)。

There isn't one definitive answer and, in practice, if it works and runs quickly enough for your needs then you can leave it as is. 没有一个明确的答案,并且在实践中,如果它的工作和运行足够快以满足您的需求,那么您可以保持原样。 Optimization is always something you can come back to. 优化始终是您可以回归的。

Joining correctly 正确加入

If you are simply checking for the existence of a join table and only including the results with that join you can do this through the correct LEFT / RIGHT JOIN expressions. 如果您只是检查是否存在连接表并且只包含该连接的结果,则可以通过正确的LEFT / RIGHT JOIN表达式来完成此操作。 This is always the first call. 这始终是第一个电话。

Expressiveness 表现

Also be as expressive as you can with SQL, you want to give it the best chance to optimize your query, there are keywords such as EXISTS, for example, make sure to use them. 也可以像SQL一样表达,你想给它最好的机会来优化你的查询,有关键字,如EXISTS,例如,确保使用它们。

Denormalization 非规范化

You can add in a column that stores the computed value, the complexity that arises out of this is ensuring that the value is always up to date. 您可以添加存储计算值的列,由此产生的复杂性是确保值始终是最新的。 This can be done by triggers or manually. 这可以通过触发器或手动完成。 The pros: 专业人士:

  • It is the easiest method of getting around slowness introduced by computed columns. 这是计算列引入的最简单的缓慢方法。

The cons: 缺点:

  • Ruins your nice normalized schema 破坏你的标准化架构
  • If you do it manually in code, you will forget to do it somewhere, causing headaches. 如果你在代码中手动执行,你将忘记在某个地方执行此操作,从而导致头痛。
  • Triggers can be a bit of a pain. 触发器可能有点痛苦。

Materialized view 物化视图

This is like denormalization but prevents polluting your normalized tables by created a stored view. 这类似于非规范化,但可以通过创建存储视图来防止污染您的规范化表。 This is achieved in MySQL by storing the result of your complex select into a results table when the values change. 这可以通过在值更改时将复杂选择的结果存储到结果表中来实现。 Again, the same as denormalization, the complexity is keeping this up to date. 同样,与非规范化相同,复杂性使这一点保持最新。 It is typically done with triggers. 它通常使用触发器完成。 This can be a pain but keeps the complexity out of your schema. 这可能很痛苦,但会使模式的复杂性降低。 As mentioned by@eggyal it isn't a supported feature of MySQL yet so you will have to DIY... Materialized views with MySQL 正如@ eggyal所提到的,它不是MySQL支持的功能,所以你必须使用MySQL来实现DIY ... 物化视图

Pros: 优点:

  • Keeps dirty denormalized stuff away from your nice normalized schema. 保持脏的非规范化的东西远离你漂亮的规范化模式。

Cons: 缺点:

  • Materialized views aren't supported so setting them up requires work. 不支持物化视图,因此设置它们需要工作。
  • If you trigger the refresh of your views in code you get stale data, but isn't quite as painful as the single column staleness of denormalization. 如果您在代码中触发视图刷新,则会获得过时的数据,但不会像单一列的非规范化过时那样痛苦。
  • Triggers can be a bit of a pain. 触发器可能有点痛苦。

If you aren't sure, and it really matters, do some benchmarking. 如果你不确定,那真的很重要,做一些基准测试。

EDIT If you code has this query in one form or another across your code base then that has the possibility of cause headaches in future as you will have to remember to change the statements in all of the places if or when they change. 编辑如果您的代码在代码库中以某种形式存在此查询,那么将来可能会引起令人头疼的问题,因为您必须记住在更改时更改所有位置的语句。

If by doing the above you have made your statements really simple and concise then they may differ enough from each other for it to not be a problem. 如果通过上述操作,您已经使您的陈述变得非常简单和简洁,那么它们可能彼此之间有足够的差异,因为它不是问题。

You can do some things to help you out: 你可以做一些事情来帮助你:

  1. Put all of the related queries in a single place, ie a single class or script that handles this query in its various forms. 将所有相关查询放在一个位置,即以各种形式处理此查询的单个类或脚本。 This way at least all of the changes are limited to the one file. 这样,至少所有更改都限于一个文件。
  2. You can, to help yourself out a bit more, do a bit of refactoring it to remove duplication between the queries. 为了帮助自己,你可以做一些重构,以消除查询之间的重复。

Also, If you feel the database information is too exposed to the code you may want to abstract it behind a view. 此外,如果您觉得数据库信息太暴露于代码,您可能希望在视图后面抽象它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM