暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

那些我很希望 MySQL 有,但 Postgres 已经有的功能

Bytebase 2025-06-24
166
原文地址:https://www.bytebase.com/blog/features-i-wish-mysql-had-but-postgres-already-has
Bytebase 深度使用 PostgreSQL 和 MySQL,两个数据库都有各自的优缺点。今天我们将着眼于 PostgreSQL 的优势和 MySQL 的不足之处。
事务性 DDL‍‍
PostgreSQL 最被低估的特性之一是对事务性 DDL 的支持:可以将架构更改包装在事务中,出现问题可以回滚;甚至在 DDL 事务中支持保存点,可以进行细粒度控制。
    -- PostgreSQL: This works!
    BEGIN;
    ALTER TABLE users ADD COLUMN email_verified BOOLEAN DEFAULT FALSE;
    SAVEPOINT after_column_add;
    CREATE INDEX idx_users_email_verified ON users(email_verified);
    -- Oops, index creation failed, but we can keep the column
    ROLLBACK TO SAVEPOINT after_column_add;
    COMMIT;
    MySQL 中,DDL 语句是自动提交的,一旦执行就无法回退。这给数据库迁移带来了潜在的风险,特别是在生产环境中。
    自定义类型和域
    PostgreSQL 允许创建自定义数据类型和域,这提供了更好的数据建模能力和更强的类型安全性。
      -- PostgreSQL: Create custom types
      CREATE TYPE mood AS ENUM ('sad''ok''happy');
      CREATE DOMAIN email AS TEXT CHECK (VALUE ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');
      CREATE TABLE users (
          id SERIAL PRIMARY KEY,
          name TEXT,
          email email,  -- Custom domain with validation
          current_mood mood  -- Custom enum type
      );
      MySQL 的 ENUM 支持有限,灵活性不足。具有内置验证规则的自定义域将保障数据库级别的数据完整性,减少应用程序级别验证的需要,并确保访问数据库的所有应用程序之间保持一致性。
      数组类型
      PostgreSQL 的原生数组支持具有强大的存储和查询列表功能,无需单独的表。
        -- PostgreSQL: Arrays are first-class citizens
        CREATE TABLE articles (
            id SERIAL PRIMARY KEY,
            title TEXT,
            tags TEXT[],  -- Array of tags
            view_counts INTEGER[]  -- Array of daily view counts
        );
        -- Query with array operations
        SELECT * FROM articles
        WHERE 'postgresql' = ANY(tags)
        AND array_length(view_counts, 1> 7;
        要注意,PostgreSQL 数组尚不支持外键约束。有了原生数组支持,通常不再需要额外的关联表来处理多对多关系,这也显著简化了数据模型。
        CTE
        MySQL 仅在 8.0 版本(2018年)中添加了基本的 CTE 支持,而 PostgreSQL 从 8.4 版本(2009年)就开始支持 CTE,功能更完整、更加成熟。
          -- PostgreSQL: Recursive CTEs for hierarchical data
          WITH RECURSIVE employee_hierarchy AS (
              -- Base case: top-level managers
              SELECT id, name, manager_id, 1 as level
              FROM employees
              WHERE manager_id IS NULL
              UNION ALL
              -- Recursive case: subordinates
              SELECT e.id, e.name, e.manager_id, eh.level + 1
              FROM employees e
              JOIN employee_hierarchy eh ON e.manager_id = eh.id
          )
          SELECT * FROM employee_hierarchy ORDER BY level, name;
          PostgreSQL 的 CTE 支持更高级的功能(如 MATERIALIZED 和 NOT MATERIALIZED 提示),可以更好地控制查询优化策略。
          行级安全 (RLS)
          PostgreSQL 的行级安全允许直接在数据库级别实现细粒度的访问控制。
            -- PostgreSQL: Enable RLS and create policies
            ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
            -- Policy for user-specific data
            CREATE POLICY user_documents ON documents
                FOR ALL TO app_user
                USING (owner_id = current_setting('app.current_user_id')::INTEGER);
            -- Policy for multi-tenant applications
            CREATE POLICY tenant_isolation ON documents
                FOR ALL TO app_user
                USING (tenant_id = current_setting('app.tenant_id')::INTEGER);
            -- Users can only see their own documents automatically
            SELECT * FROM documents;  -- Only returns user's documents in their tenant
            虽然 RLS 很擅长简单的 user_id 或 tenant_id 过滤,但授权规则涉及角色、权限或动态关系时,事情就会变得复杂。当然,它仍是数据库安全链中重要的深度防御机制,确保即使应用程序级别的防护失效,敏感数据仍然受到保护。
            至于 MySQL,它缺乏内置的 RLS,所以访问控制不得不在应用程序代码中实现,或通过复杂的视图结构来实现。
            部分索引
            PostgreSQL 允许创建带 WHERE 子句的索引,对于特定查询模式更加简单高效。
              -- PostgreSQL: Index only active users
              CREATE INDEX idx_active_users ON users (last_login)
              WHERE status = 'active';
              -- Index only pending orders
              CREATE INDEX idx_pending_orders ON orders (created_at)
              WHERE status = 'pending';
              MySQL 要求索引整个列;如果只需查询数据子集,冗余的查询就会拖慢速度。
              空间支持
              两个数据库都支持空间数据,但 PostgreSQL 通过 PostGIS 插件提供了更全面的地理空间功能。
                -- PostgreSQL with PostGIS: Advanced spatial queries
                SELECT name,
                       ST_Distance(location, ST_MakePoint(-73.93524240.730610)) as distance_km
                FROM restaurants
                WHERE ST_DWithin(location, ST_MakePoint(-73.93524240.730610), 1000)  -- Within 1km
                ORDER BY location <-> ST_MakePoint(-73.93524240.730610)  -- KNN search
                LIMIT 10;
                MySQL 的空间支持虽然在进步,但在深度和性能上无法匹敌 PostGIS。对于需要严肃地理空间功能的应用程序,PostgreSQL 和 PostGIS 明显更胜一筹。
                向量支持
                PostgreSQL 紧跟 AI 潮流推出 pgvector,接入向量存储和相似性搜索。
                  -- PostgreSQL with pgvector: Store and search embeddings
                  CREATE TABLE documents (
                      id SERIAL PRIMARY KEY,
                      content TEXT,
                      embedding VECTOR(1536)  -- OpenAI embedding dimension
                  );
                  -- Find similar documents using cosine similarity
                  SELECT content, 1 - (embedding <=> '[0.1, 0.2, ...]'::vector) AS similarity
                  FROM documents
                  ORDER BY embedding <=> '[0.1, 0.2, ...]'::vector
                  LIMIT 5;
                  MySQL 最近在 9.0 版本中添加了向量支持,包括基本的 VECTOR 数据类型和有限的距离函数,但 PostgreSQL 的 pgvector 扩展仍然更成熟,具有更广泛的操作符支持、更好的索引选项(IVFFlat、HNSW)和更丰富的向量操作生态系统。
                  解析器
                  PostgreSQL 更严格地遵循 SQL 标准,提供更详细的报错信息,更可预测。MySQL 的解析器则向来较为宽松,因此 SQL 更不易移植,而且容易出现细节上的 bug。
                  从工具开发者的角度,libpg_query(https://github.com/pganalyze/libpg_query)项目实际上提取了 PostgreSQL 的解析器代码,与 PostgreSQL SQL 解析行为 100% 兼容。MySQL 最广泛使用的解析器来自 TiDB(https://github.com/pingcap/tidb/tree/master/pkg/parser),但存在兼容性差异,因为它是专门为 TiDB 的需求而构建的。
                  开放性
                  由于 PostgreSQL 许可证宽松(类似于 BSD)、架构可扩展,开发者得以完全自由地嵌入、修改或商业化数据库。它的社区公开运作:设计讨论在公开的 pgsql-hackers 邮件列表进行,每次提交都有注释。比如最近 PG 18 添加的虚拟生成列和 NOT VALID NOT NULL 约束。

                  pgsql-hackers:https://www.postgresql.org/list/pgsql-hackers

                  虚拟生成列:https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=83ea6c54025bea67bcd4949a6d58d3fc11c3e21b

                  NOT VALID NOT NULL:https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=a379061a22a8fdf421e1a457cc6af8503def6252

                  相比之下,MySQL 的双重许可模式(GPL 加商业许可)限制了下游选择,bug 跟踪器不透明(https://bugs.mysql.com),而且对社区和原始报告者隐藏某些问题。
                  正如 MongoDB CEO 在 FY26 Q1 财报电话会议所说:

                  「开源、开放标准,最重要的是,不被任何单一供应商所拥有。」

                  PostgreSQL 以 MySQL 无法做到的方式具象化了这一理想。


                  Bytebase 3.7.1 - 数据库变更功能全免费!

                  MySQL 阵营又一大将投奔 Postgres,加入 Supabase 打造全新分布式数据库

                  DBA 视角:Postgres 18 新版本,带来了哪些变化?

                  开发者前沿 #10|早期计算机和游戏机中像素宽高比的多样性

                  文章转载自Bytebase,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论