【发布时间】:2012-01-27 23:34:00
【问题描述】:
我需要检索与列表中存储的 ID 匹配的记录。运行时生成的查询很简单:
SELECT [whatever FROM sometable] WHERE (id = 1) or (id = 5) or (id = 33).
相当于
SELECT [whatever FROM sometable] WHERE [id] IN (1, 5, 33);
这很好,但如果列表包含成百上千个 ID 怎么办?该语句将很大,并且在某些时候 SQL 解析器可能会发出嘶哑的声音,或者如果没有,性能可能会非常糟糕。 我怎样才能以一种对检索到的记录数量不那么敏感的方式来做到这一点?
(我不能只遍历列表并逐个检索记录的原因是我需要数据库为我执行 ORDER BY。记录必须来自按特定字段排序的数据库,而该列表表示用户在网格中选择的记录,可以以多种方式排序。是的,我可以在检索记录后用代码对记录进行排序,但这是 B 计划,因为我什至不需要持有它们都在一个数据结构中,只是为了正确排序。)
【问题讨论】:
-
你能把所有的 id 放到一个临时表中,然后说 SELECT [whatever FROM sometable] WHERE [id] IN (SELECT id FROM #temptable) 吗?
-
我有更多的想法。 1)好的设计会阻止任何列表显示数千个ID。无论如何,人类一次只能看一个屏幕。人类很有可能正在对这些信息进行一些汇总。为他们做! 2)我根本无法相信循环查询的唯一原因。曾经! (我可能会在那里受热)。绝不! SQL 太强大了。这表明模型存在问题。把你的模型带到第三范式。它的工作量很小,但它在可扩展性方面带来了好处。
-
@Matt: (1) 说来话长,我希望避免它 :) 它是剪贴板管理器中的剪辑列表,但它可能是书签管理器中的 URL 等。显示可能已经被过滤(例如,仅今天添加的项目),用户通常只选择一个项目,或一次选择几个。但该应用程序没有施加任何任意限制。如果它恰好显示 2k 个项目并且用户点击 Ctrl+A 然后“导出”,那么我需要优雅地处理这个问题,即使这是一种罕见的情况。 (续)
-
(续)因为这些是剪辑,通常明智的做法是按时间顺序排列它们,即使它们目前是按字母顺序或长度等排序(用户决定)。这就是为什么选择的顺序可能不是记录需要来自数据库的顺序。 (2) 我同意循环。我问是因为我想避免它。
-
因为有一个按时间顺序排列的附件,所以按日期分页。我仍然认为将这么多记录放在一个列表中是一种糟糕的做法。看看谷歌浏览器是如何做到的。历史/书签。添加按日期范围过滤器导出,按当前视图中选择的方式导出,并导出所有功能,您应该对几乎所有用户都很满意。或者,如果他们确实需要这么大的粒度而不是提供大视图,请提供一个过滤器控制系统,帮助他们缩小列表中的结果。甚至是“包含”导出功能。
标签: sql performance sqlite