可用版本: Dev (3.21) | 最新 (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11

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

看起来很明显,不是吗?最好不要偷懒,仔细设计你的查询。再次,这篇博文深入解释了这个主题

反馈

您对此页面有任何反馈吗? 我们很乐意听取您的意见!

The jOOQ Logo