确保“合理”查询

时间:2010-01-06 19:25:12

标签: c# asp.net sql sql-server

在我们的组织中,我们需要让员工通过提供WHERE子句来过滤我们的Web应用程序中的数据。它长期以来运行良好,但我们偶尔遇到用户提供需要对大型表或低效连接等进行全表扫描的查询。

有些小丑可能会写下这样的话:

select * from big_table where
Name in (select name from some_table where name like '%search everything%')
or name in ('a', 'b', 'c')
or price < 20
or price > 40
or exists (select 1 from some_other_table where col1 + col2 + col3 = 4)
or exists (select 1 from table_a, table+b)

显然,这不是一个很好的方法来查询这些表,包括计算值,非索引列,大量OR和table_a和table_b上的无限制连接。

但对于用户来说,这可能是完全有道理的。

那么,允许内部用户向数据库提供查询同时确保它不会锁定十几个表并挂起网络服务器5分钟的最佳方法是什么?

我猜这是c#/ sql-server中的一种编程方式,可以在运行之前获取查询的执行计划。如果是这样,哪些因素会导致成本?估计的I / O成本?估算的CPU成本?什么是合理的限制,告诉用户他的查询不好?

编辑:我们是一家市场研究公司。我们有数以千计的调查,每个调查都有自己的数据。我们有数十名研究人员希望以任意方式对数据进行切片。我们有工具让他们使用GUI构建“有效”过滤器,但是一些“高级用户”想要提供他们自己的查询。我意识到这不是标准或最佳实践,但我怎样才能让许多用户使用任意复杂的条件和不断变化的条件来查询表所需的行?

11 个答案:

答案 0 :(得分:5)

你的问题的前提是:

在我们的组织中,我们需要让员工通过提供WHERE子句来过滤我们的Web应用程序中的日期。

我觉得这个前提是有缺陷的。我无法想象我会允许用户这样做的情况。除了您已经发现的问题之外,您还要接受SQL注入攻击。

我强烈建议您重新评估您的要求,看看您是否无法构建更安全,更专注的方式来让用户进行搜索。

但是,如果您的用户确实非常复杂(并且信任!)足以直接提供WHERE子句,那么他们需要了解他们可以做什么,不能作为过滤器提交。

答案 1 :(得分:3)

您可以尝试使用以下内容:

SET SHOWPLAN_ALL ON
GO
SET FMTONLY ON
GO
<<< Your SQL code here >>>
GO
SET FMTONLY OFF
GO
SET SHOWPLAN_ALL OFF
GO

然后你可以解析你所拥有的东西。至于在各种事物上画线的地方,这将需要一些经验。有一些东西需要注意,但没有任何东西可以切割和干燥。检查查询计划而不是科学通常更具艺术性。

正如其他人所指出的那样,我认为你的问题比技术含义更深入。您让不合格的人以这种方式访问​​您的数据库这一事实是潜在的问题。根据过去的经验,我经常在他们懒得或缺乏经验的公司中看到这一点,无法正确捕捉他们的应用程序的要求。我并不是说你的企业环境就是这种情况,但这就是我所见过的。

答案 2 :(得分:2)

除了试图控制用户输入的内容(这是一场失败的战斗,总会有一个新的雇员会提出一个富有想象力的查询),我会调查资源调控器,见{{3} }。您将临时查询放入单独的池中并限制分配的资源。这样,您可以通过限制错误查询可以对其他任务执行的损坏来缓解此问题。

您还应该考虑通过其他方式访问数据,例如Managing SQL Server Workloads with Resource Governor,并让用户在他们自己的Excel上按照他们想要的方式按摩他们的数据。业务用户喜欢这一点,并且对transaciton processign服务器的影响微乎其微。

答案 3 :(得分:1)

不是允许员工直接编写(追加)查询,然后在运行查询之前尝试计算查询成本,为什么不创建某种高级搜索或过滤功能,而不是编写无法控制的SQL?

答案 4 :(得分:1)

在内部应用程序的非常大的企业起源中,这是一种常见做法。通常在您的设计阶段,您将限制标准或对数据范围设置合理的限制,但是一旦业务获得应用程序,将会有来自业务部门管理层的调用来删除限制。在我的起源中,这是一个管理问题,而不是工程问题。

我们所做的是对所有条件进行了分析,发现最大的违法者,用户和查询类型导致的问题最多,并对某些查询设置了限制。此外,定期使用的一些非常昂贵的查询已添加到应用程序中,应用程序缓存了结果并在负载较低时运行查询。我们还为标准用户创建了caned优化查询,并且只为指定用户提供了搜索任何内容的能力。只是几个想法。

答案 5 :(得分:1)

您可以为数据库创建数据模型,并允许用户使用SQL Reporting Services的报表生成器。它基于GUI并且不需要编写WHERE子句,因此应该限制他们可以做多少伤害。

或者您可以为了用户查询而存储数据库的副本,每小时更新一次数据库,然后让他们去城镇......:)

答案 6 :(得分:1)

我曾经在一些地方工作过。我们最终做的是不允许用户无限制地访问,并承诺让IT尽力在需要时提供查询。问题是数据库相当复杂,即使用户可以在语法和语法上编写正确的SQL,他们也不一定了解表之间的关系。换句话说,即使他们可以编写自己的SQL,他们也会得到错误的答案。我们使用户相信,基于对数据库中200个表的有缺陷或不完整的理解做出错误决策的风险太高。最好在一天之后得到正确的答案而不是错误的答案。

另一部分是当用户A写入查询并获得1个答案时IT部门做了什么,然后用户B写出他认为是同一个查询并获得不同答案的内容?找到差异是否是IT的工作?修复这两个SQL?最重要的是,我不允许他们访问。我会像其他人提到的那样用预定义的查询加载系统,并尝试训练mgmt为什么这是它长期运行的唯一方法。

答案 7 :(得分:1)

如果您拥有如此多的数据并希望向客户提供按照自己的意愿分析和查看信息的能力,我强烈建议您使用 OLAP 技术。

答案 8 :(得分:0)

我猜你从来没有听说过SQL注入攻击?如果用户在WHERE子句后输入A DROP DATABASE命令怎么办?

答案 9 :(得分:0)

这就是绝大多数应用程序中几乎从未向用户提供直接SELECT权限的原因。

更好的方法是围绕用例设计应用程序,以便您能够使用专门设计的过滤器/聚合/布局选项覆盖合理百分比的需求。

有很多方法可以做到这一点,因此必须对特定问题领域进行一些分析,并研究可行的方法。

虽然直接SQL访问对您的用户来说是最灵活的,但长时间执行查询可能只是您头痛的开始。 SQL注入是一个很大的问题,无论它的来源是恶意的还是简单的误导。

答案 10 :(得分:0)

(乍得在评论中提到这一点,但我认为它应该是一个答案。)

也许你应该将需要特别查询的数据复制到一个单独的数据库中,以隔离大多数用户的任何问题。