SQL: SELECT *
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
引入 SELECT *
语法主要是为了方便即席 SQL。能够快速检查生产系统上的数据以查看可用的内容非常有用。对于这些情况,我们通常不关心提供有意义的 SELECT 子句。我们只是想投影所有内容,例如
SELECT * FROM book
create.select(asterisk()).from(BOOK).fetch();
但是在现实世界的应用程序中,我们不应该这样做,无论是在 SQL 中还是在 jOOQ 中。我们应该只限制自己投影我们真正需要的那些列。这里的关键是只投影我们需要的东西,所以这与 *
(星号作为语法标记)无关,但同样可以明确列出所有列,例如
SELECT id, author_id, title, published_in, language_id, ... FROM book
create.select( BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE, BOOK.PUBLISHED_IN, BOOK.LANGUAGE_ID, ...) .from(BOOK).fetch();
这篇博文深入解释了为什么 SELECT *
是不好的做法(不是星号有错,而是盲目投影所有内容,包括在使用 jOOQ 的 selectFrom(Table)
时)。主要问题是你正在服务器上创建不必要的强制性工作
- 不必要的,因为你在获取数据后立即丢弃了它
- 强制性的,因为 SQL 优化器不知道这一点,因此它必须提供数据
这至少有以下影响
- 磁盘 I/O:服务器必须从磁盘读取所有数据,这些数据可能会卸载到 LOB 存储或其他地方。如果您的表很宽,那么这可能会很严重!
- 内存消耗:在服务器和客户端上,您都在浪费内存以及将数据从内存传输到内存的关联 CPU 周期,只是为了再次丢弃它。服务器甚至可能将所有这些数据不必要地缓存在“缓冲区缓存”中。
- 索引使用:所谓的“覆盖索引”不能以这种方式使用,例如,当您的关系表除了外键之外还有其他列时,投影这些列可能会使查询慢得多,而不是仅仅使用覆盖索引。
- 连接消除:一些更高级的 SQL 转换是不可能做到的,例如
JOIN
消除转换,其中整个连接都从您的查询中删除,因为它们被证明是不必要的。但只有当您没有从表中投影任何内容时,它们才是不必要的。如果你这样做,那么必须执行JOIN
。
看起来很明显,不是吗?最好不要偷懒,仔细设计你的查询。再次,这篇博文深入解释了这个主题。
反馈
您对此页面有任何反馈吗? 我们很乐意听取您的意见!