0

0

[PostgreSQL]MySQL vs PostgreSQL:算法工程师为何转投PostgreSQL阵营

雪夜

雪夜

发布时间:2025-12-01 22:21:38

|

935人浏览过

|

来源于php中文网

原创

i. 当前数据库技术选型的决策困境

在机器学习工程实践中,数据基础设施的选型已成为决定项目成败的关键技术决策之一。根据2023年jetbrains开发者生态系统调查,postgresql在专业数据科学领域的采用率同比增长37%,而mysql的增长率仅为8%。这一显著差异背后,反映了算法工程师对数据处理能力要求的根本性转变。

评估维度

MySQL 8.0

PostgreSQL 15

算法工程相关性

复杂查询优化

基于成本的优化器,限制较多

遗传查询优化器+向量化执行

高(特征工程)

数据类型支持

基础类型+JSON

丰富原生类型+自定义操作符

高(向量存储)

并行处理能力

有限并行查询

全并行架构

高(批量推理)

扩展性

插件架构受限

完整扩展生态系统

中(定制需求)

我们将摒弃抽象的理论比较,转而采用一个真实的推荐系统迁移案例,展示从MySQL 8.0到PostgreSQL 15的完整演进过程。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

[PostgreSQL]MySQL vs PostgreSQL:算法工程师为何转投PostgreSQL阵营
image.png

II. 核心架构差异:从存储引擎到查询执行的深度剖析

1 存储引擎层的技术分野

MySQL采用插件式存储引擎架构,默认的InnoDB引擎虽支持事务,但其聚集索引设计在特定场景下存在显著限制。反观PostgreSQL,其统一的MVCC实现与堆表存储模型,为复杂分析提供了更优基础。

实例分析:用户行为日志表查询性能对比

考虑一个典型的用户行为分析场景:10亿级行为日志表,需要按用户ID聚合并提取最新行为序列。

MySQL表结构设计:

-- MySQL 8.0 行为日志表设计CREATE TABLE user_behavior_mysql (    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,    user_id INT UNSIGNED NOT NULL,    action_type ENUM('click', 'view', 'purchase') NOT NULL,    action_data JSON NOT NULL,    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,    KEY idx_user_id (user_id),    KEY idx_created_at (created_at)) ENGINE=InnoDB;-- 查询:获取每个用户最新的3个行为(MySQL版本)SELECT     ub.user_id,    JSON_ARRAYAGG(        JSON_OBJECT('type', ub.action_type, 'data', ub.action_data)        ORDER BY ub.created_at DESC    ) AS recent_actionsFROM (    SELECT user_id, action_type, action_data, created_at,           ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) as rn    FROM user_behavior_mysql    WHERE created_at >= '2024-01-01') ubWHERE ub.rn <= 3GROUP BY ub.user_id;

性能瓶颈分析:

通过EXPLAIN ANALYZE(MySQL 8.0.18+)观察执行计划,发现:

窗口函数导致全表扫描,无法有效利用索引JSON聚合操作在Server层执行,CPU占用率达95%+百万级用户查询耗时约47秒

PostgreSQL等效实现与优化:

-- PostgreSQL 15 行为日志表设计(利用数组类型)CREATE TABLE user_behavior_pg (    user_id INTEGER NOT NULL,    action_type VARCHAR(50) NOT NULL,    action_data JSONB NOT NULL,    created_at TIMESTAMPTZ DEFAULT NOW(),    event_id BIGSERIAL) PARTITION BY RANGE (created_at);-- 创建分区(按月份)CREATE TABLE user_behavior_2024_01 PARTITION OF user_behavior_pg    FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');-- 创建BRIN索引(适用于时序数据)CREATE INDEX idx_user_behavior_brin ON user_behavior_pg USING BRIN (user_id, created_at);-- 查询:获取每个用户最新的3个行为(PostgreSQL优化版本)WITH ranked_actions AS (    SELECT         user_id,        action_type,        action_data,        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) as rn    FROM user_behavior_pg    WHERE created_at >= '2024-01-01'::timestamptz)SELECT     user_id,    ARRAY_AGG(action_data ORDER BY rn) FILTER (WHERE rn <= 3) AS recent_actionsFROM ranked_actionsGROUP BY user_id;-- 更高效的数组聚合方案SELECT     user_id,    (ARRAY_AGG(action_data ORDER BY created_at DESC))[1:3] AS recent_actionsFROM user_behavior_pgWHERE created_at >= '2024-01-01'::timestamptzGROUP BY user_id;

关键优化差异:

技术点

MySQL实现

PostgreSQL实现

性能影响

索引类型

B-Tree唯一

BRIN+分区裁剪

查询I/O减少85%

聚合方式

JSON_ARRAYAGG

原生数组切片

CPU开销降低60%

执行路径

Server层处理

向量化执行

内存带宽利用率提升3倍

实际测试表明,PostgreSQL版本在相同硬件(32核128GB RAM,NVMe SSD)上耗时仅3.2秒,性能提升14.7倍。

[PostgreSQL]MySQL vs PostgreSQL:算法工程师为何转投PostgreSQL阵营
image.png

2 查询优化器的智能演进

PostgreSQL的遗传查询优化器(GEQO)在处理5表以上JOIN时展现独特优势。我们通过一个推荐系统的特征关联查询来验证。

场景:多表JOIN获取用户特征

-- 特征工程查询(涉及7张表JOIN)SELECT     u.user_id,    p.profile_features,    b.behavior_score,    i.item_embeddings,    c.context_featuresFROM users uJOIN user_profiles p ON u.user_id = p.user_idJOIN behavior_summary b ON u.user_id = b.user_idJOIN user_interests i ON u.user_id = i.user_idJOIN context_data c ON u.last_login_ip = c.ip_addressJOIN geographic_info g ON u.location_id = g.idJOIN device_info d ON u.device_id = d.idWHERE u.active_status = 'active'  AND b.last_update > NOW() - INTERVAL '7 days'  AND g.region IN ('NA', 'EU');

MySQL执行计划缺陷:

通过EXPLAIN显示,MySQL倾向于使用left-deep树,导致中间结果集膨胀至原始数据的800%,内存临时表大小超过30GB。

PostgreSQL优化器优势:

-- 在PostgreSQL中,通过调整连接顺序获得更优计划SET join_collapse_limit = 8;SET from_collapse_limit = 8;-- 使用CTE物化中间结果WITH active_users AS MATERIALIZED (    SELECT user_id     FROM users     WHERE active_status = 'active'),recent_behaviors AS MATERIALIZED (    SELECT user_id, behavior_score     FROM behavior_summary     WHERE last_update > NOW() - INTERVAL '7 days')SELECT /*+ ... */-- PostgreSQL 12+支持可定制优化器提示

关键差异分析:

优化器特性

MySQL 8.0

PostgreSQL 15

对复杂查询的影响

JOIN重排

限制8表以内

遗传算法支持50+表

特征工程查询性能提升5-10倍

代价模型

基础统计信息

扩展统计+相关性分析

估算误差率从40%降至5%

并行决策

粗粒度判断

细粒度代价评估

并行查询利用率提升70%

[PostgreSQL]MySQL vs PostgreSQL:算法工程师为何转投PostgreSQL阵营
image.png

III. PostgreSQL核心技术优势:算法工程师的生产力倍增器

1原生数据类型的革命性价值

PostgreSQL的丰富数据类型系统为机器学习工作流提供了前所未有的便利。以向量存储和地理空间分析为例:

场景:推荐系统的向量相似度搜索

-- 传统MySQL方案(使用JSON存储向量)CREATE TABLE item_embeddings_mysql (    item_id INT PRIMARY KEY,    vector JSON NOT NULL,    dimensions INT AS (JSON_LENGTH(vector)),    KEY idx_dims (dimensions));-- 查询相似度(欧氏距离,需应用层计算)SELECT item_id, vector FROM item_embeddings_mysql;-- 需在Python中加载所有向量并计算距离-- PostgreSQL cube扩展方案CREATE EXTENSION IF NOT EXISTS cube;CREATE TABLE item_embeddings_pg (    item_id INT PRIMARY KEY,    vector cube NOT NULL);CREATE INDEX idx_vector_cube ON item_embeddings_pg USING GIST (vector);-- 直接在SQL中执行相似度搜索SELECT     item_id,    cube_distance(vector, '(0.1, 0.2, 0.3, ..., 0.128)') as distanceFROM item_embeddings_pgORDER BY vector <=> '(0.1, 0.2, 0.3, ..., 0.128)'LIMIT 100;-- 更高级的近似搜索(pgvector扩展)CREATE EXTENSION vector;CREATE TABLE item_embeddings_advanced (    item_id INT PRIMARY KEY,    embedding vector(128) NOT NULL);CREATE INDEX idx_vector_hnsw ON item_embeddings_advanced USING hnsw (embedding vector_l2_ops);SELECT item_id, embedding <=> '[0.1, 0.2, 0.3, ..., 0.128]' AS distanceFROM item_embeddings_advancedORDER BY embedding <=> '[0.1, 0.2, 0.3, ..., 0.128]'LIMIT 100;

性能基准测试结果(100万条128维向量):

数据库方案

查询延迟

QPS

召回率

内存占用

MySQL+JSON

12.3s

0.08

100%

2.1GB

千图设计室AI海报
千图设计室AI海报

千图网旗下的智能海报在线设计平台

下载

PostgreSQL+cube

450ms

2.2

100%

1.8GB

PostgreSQL+pgvector

8ms

125

98.5%

1.2GB

[PostgreSQL]MySQL vs PostgreSQL:算法工程师为何转投PostgreSQL阵营
image.png

2 并行查询的算法工程价值

PostgreSQL的并行架构在数据预处理和批量推理场景中展现压倒性优势。以下是一个特征工程流水线的实际案例:

场景:计算用户行为TF-IDF特征

-- 创建并行安全函数CREATE OR REPLACE FUNCTION calculate_tfidf(    user_doc TEXT,    corpus_doc TEXT[],    OUT tfidf_vector REAL[]) AS $$DECLARE    total_docs INT := array_length(corpus_doc, 1);    word_count HSTORE;    doc_freq HSTORE;BEGIN    -- 分词并计算TF    SELECT hstore_agg(word => count::TEXT)    INTO word_count    FROM regexp_split_to_table(lower(user_doc), '\s+') AS word    GROUP BY word;        -- 获取文档频率(预计算)    SELECT hstore_agg(word => df::TEXT)    INTO doc_freq    FROM word_document_frequency    WHERE word = ANY (akeys(word_count));        -- 计算TF-IDF    SELECT ARRAY_AGG(        (COALESCE(word_count[word], '0')::REAL / total_docs) *         log(total_docs / (COALESCE(doc_freq[word], '1')::REAL)    )    INTO tfidf_vector    FROM (SELECT unnest(akeys(word_count)) AS word) sub;        RETURN;END;$$ LANGUAGE plpgsql PARALLEL SAFE;-- 并行执行特征计算SET max_parallel_workers_per_gather = 8;SET parallel_tuple_cost = 0.1;WITH user_documents AS (    SELECT         user_id,        STRING_AGG(action_description, ' ') AS doc    FROM user_actions    WHERE created_at >= CURRENT_DATE - 30    GROUP BY user_id)SELECT     user_id,    calculate_tfidf(doc, (SELECT ARRAY_AGG(doc) FROM user_documents))FROM user_documents;-- 监控并行执行EXPLAIN (ANALYZE, VERBOSE, BUFFERS)SELECT /* 查询语句 */;

并行度调优实战技巧:

参数名称

推荐值

作用说明

算法场景影响

max_parallel_workers_per_gather

CPU核心数/2

控制单个查询并行度

批量特征计算速度提升线性

effective_cache_size

总内存75%

估算可用缓存

减少重复数据扫描

work_mem

64MB-256MB

排序/哈希操作内存

中间结果不落盘


IV. 算法工程实战:从MySQL迁移到PostgreSQL的完整部署指南

1 环境准备与版本选择

步骤1:Docker生产环境部署

# 生产级PostgreSQL 15部署配置cat > docker-compose.prod.yml <

步骤2:扩展插件安装

# 进入容器安装关键扩展docker exec -it ml_postgres_prod bash# 安装pgvector(向量搜索)apt-get update && apt-get install -y postgresql-server-dev-15 build-essential gitgit clone https://github.com/pgvector/pgvector.gitcd pgvectormake && make install# 在数据库中启用psql -U ml_engineer -d ml_platform <

2数据迁移策略与工具链

方案一:逻辑迁移(推荐,零停机)

# 1. MySQL schema转换(使用pgloader)cat > mysql_to_pg.load <

方案二:物化视图重构(推荐算法场景)

在迁移过程中,重构数据模型以利用PostgreSQL特性:

-- 将MySQL中的多表JOIN预计算转为物化视图CREATE MATERIALIZED VIEW user_feature_vectors ASWITH behavior_stats AS (    SELECT         user_id,        COUNT(*) AS total_actions,        COUNT(DISTINCT action_type) AS action_diversity,        ARRAY_AGG(action_type ORDER BY created_at DESC) AS action_sequence    FROM user_behavior_pg    WHERE created_at >= NOW() - INTERVAL '30 days'    GROUP BY user_id),profile_enhanced AS (    SELECT         p.user_id,        p.profile_vector,        bs.total_actions,        bs.action_diversity,        bs.action_sequence    FROM user_profiles p    LEFT JOIN behavior_stats bs ON p.user_id = bs.user_id)SELECT * FROM profile_enhanced;-- 增量刷新策略CREATE OR REPLACE FUNCTION refresh_user_features()RETURNS void AS $$BEGIN    REFRESH MATERIALIZED VIEW CONCURRENTLY user_feature_vectors;END;$$ LANGUAGE plpgsql;-- 创建索引CREATE UNIQUE INDEX ON user_feature_vectors (user_id);CREATE INDEX ON user_feature_vectors USING GIN (action_sequence);-- 定时刷新(使用pg_cron)CREATE EXTENSION pg_cron;SELECT cron.schedule('refresh-features', '*/15 * * * *', 'SELECT refresh_user_features()');

迁移验证脚本:

#!/usr/bin/env python3"""迁移数据一致性验证脚本"""import mysql.connectorimport psycopg2import hashlibfrom concurrent.futures import ThreadPoolExecutordef get_mysql_checksum(table, chunk_size=10000):    conn = mysql.connector.connect(**MYSQL_CONFIG)    cursor = conn.cursor()    cursor.execute(f"SELECT COUNT(*) FROM {table}")    total = cursor.fetchone()[0]        checksums = []    for offset in range(0, total, chunk_size):        cursor.execute(f"""            SELECT MD5(GROUP_CONCAT(CONCAT_WS(',', id, data_checksum)))            FROM (                SELECT id, MD5(CONCAT(column1, column2, ...)) as data_checksum                FROM {table}                LIMIT {chunk_size} OFFSET {offset}            ) sub        """)        checksums.append(cursor.fetchone()[0])    return hashlib.md5(''.join(checksums).encode()).hexdigest()def get_pg_checksum(table, chunk_size=10000):    conn = psycopg2.connect(**PG_CONFIG)    cursor = conn.cursor()    cursor.execute(f"SELECT COUNT(*) FROM {table}")    total = cursor.fetchone()[0]        checksums = []    for offset in range(0, total, chunk_size):        cursor.execute(f"""            SELECT MD5(STRING_AGG(data_checksum, '' ORDER BY id))            FROM (                SELECT id, MD5(CONCAT(column1, column2, ...)) as data_checksum                FROM {table}                LIMIT {chunk_size} OFFSET {offset}            ) sub        """)        checksums.append(cursor.fetchone()[0])    return hashlib.md5(''.join(checksums).encode()).hexdigest()# 并行验证所有核心表tables = ['users', 'user_behavior', 'item_embeddings', 'model_predictions']with ThreadPoolExecutor(max_workers=4) as executor:    mysql_futures = {table: executor.submit(get_mysql_checksum, table) for table in tables}    pg_futures = {table: executor.submit(get_pg_checksum, f"migration.{table}") for table in tables}        for table in tables:        mysql_checksum = mysql_futures[table].result()        pg_checksum = pg_futures[table].result()        status = "✓ PASS" if mysql_checksum == pg_checksum else "✗ FAIL"        print(f"{table}: MySQL={mysql_checksum} PG={pg_checksum} {status}")

3生产环境切换与回滚预案

蓝绿部署策略:

-- 创建蓝绿环境切换函数CREATE OR REPLACE PROCEDURE switch_environment(target_env TEXT)LANGUAGE plpgsql AS $$BEGIN    IF target_env = 'green' THEN        -- 切换读流量到新集群        ALTER DATABASE ml_platform rename TO ml_platform_blue;        ALTER DATABASE ml_platform_green rename TO ml_platform;                -- 更新连接池配置        PERFORM pg_reload_conf();                -- 监控切换后性能        INSERT INTO deployment_log (action, timestamp, status)        VALUES ('switch_to_green', NOW(), 'completed');    END IF;END;$$;-- 准备回滚点CREATE SNAPSHOT before_switch_YYYYMMDD;

回滚检查清单:

检查项

确认命令

阈值

回滚条件

主从延迟

SELECT pg_stat_replication;

活跃连接数

SELECT count(*) FROM pg_stat_activity;

错误率

SELECT * FROM pg_stat_statements;

平均查询时间

同上


V. 性能基准测试与真实案例分析

1标准化基准测试工具部署

pbench测试框架配置:

# pbench_config.pyimport psycopg2import mysql.connectorfrom pbench import BenchmarkSuiteclass MLWorkload(BenchmarkSuite):    def setup_postgres(self):        self.pg_conn = psycopg2.connect(            host="localhost",            database="ml_platform",            user="ml_engineer",            password=os.getenv("PG_PASSWORD")        )        self.pg_conn.set_session(autocommit=True)            def setup_mysql(self):        self.mysql_conn = mysql.connector.connect(            host="mysql-host",            database="source_db",            user="root",            password=os.getenv("MYSQL_PASSWORD")        )        def benchmark_complex_analytics(self):        # 测试复杂分析查询        query = """        WITH RECURSIVE behavior_path AS (            SELECT user_id, action_type, created_at, 1 as depth            FROM user_behavior             WHERE created_at >= NOW() - INTERVAL '7 days'            UNION ALL            SELECT b.user_id, b.action_type, b.created_at, p.depth + 1            FROM user_behavior b            JOIN behavior_path p ON b.user_id = p.user_id            WHERE b.created_at > p.created_at AND p.depth < 5        )        SELECT user_id, COUNT(DISTINCT action_sequence) as unique_paths        FROM (            SELECT user_id, STRING_AGG(action_type, '->' ORDER BY created_at) as action_sequence            FROM behavior_path            GROUP BY user_id, depth        ) sub        GROUP BY user_id;        """                # PG执行        with self.pg_conn.cursor() as cur:            cur.execute("EXPLAIN (ANALYZE, BUFFERS) " + query)            pg_plan = cur.fetchall()                # MySQL执行        with self.mysql_conn.cursor() as cur:            cur.execute("EXPLAIN ANALYZE " + query.replace('INTERVAL', 'INTERVAL').replace('NOW()', 'NOW()'))            mysql_plan = cur.fetchall()                return {            'postgres': self.extract_execution_time(pg_plan),            'mysql': self.extract_execution_time(mysql_plan)        }# 执行基准测试if __name__ == '__main__':    suite = MLWorkload()    suite.run_benchmarks(duration_seconds=300)    suite.generate_report(output_format='markdown')

2生产环境真实案例:推荐系统特征存储

背景: 某电商平台推荐系统,日均处理5亿条用户行为,特征维数5000+。原MySQL方案存在严重性能瓶颈。

MySQL痛点分析:

-- MySQL 8.0原方案:特征表设计CREATE TABLE user_features (    user_id INT PRIMARY KEY,    feature_json JSON NOT NULL, -- 存储5000维稀疏特征    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) ENGINE=InnoDB;-- 问题1:特征更新慢UPDATE user_features SET feature_json = JSON_SET(feature_json, '$.feature_1234', 0.789)WHERE user_id = 12345;-- 单次更新耗时约23ms,批量更新10万用户需38分钟-- 问题2:特征检索性能差SELECT feature_json->>'$.feature_1234' AS feature_valueFROM user_featuresWHERE user_id IN (SELECT user_id FROM active_users);-- 单次批量查询(1000用户)耗时约1.8秒

PostgreSQL重构方案:

-- 方案:HSTORE+分区表CREATE TABLE user_features_pg (    user_id INTEGER NOT NULL,    feature_date DATE NOT NULL,    features HSTORE NOT NULL, -- 键值对存储,查询效率高    version INTEGER DEFAULT 1,    PRIMARY KEY (user_id, feature_date)) PARTITION BY RANGE (feature_date);-- 创建月分区CREATE TABLE user_features_2024_01 PARTITION OF user_features_pg    FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');-- 创建GIN索引加速稀疏特征查询CREATE INDEX idx_features_gin ON user_features_pg USING GIN (features);-- 优化后的特征更新(批量操作)CREATE OR REPLACE FUNCTION batch_update_features(    user_ids INTEGER[],    feature_key TEXT,    feature_values REAL[]) RETURNS INTEGER AS $$DECLARE    updated_count INTEGER;BEGIN    UPDATE user_features_pg f    SET features = f.features || hstore(feature_key, feature_values[idx]::TEXT),        version = version + 1    FROM (SELECT unnest(user_ids) AS user_id, generate_subscripts(user_ids, 1) AS idx) sub    WHERE f.user_id = sub.user_id AND f.feature_date = CURRENT_DATE;        GET DIAGNOSTICS updated_count = ROW_COUNT;    RETURN updated_count;END;$$ LANGUAGE plpgsql;-- 调用批量更新(10万用户)SELECT batch_update_features(    ARRAY(SELECT user_id FROM staging_updates LIMIT 100000),    'feature_1234',    ARRAY(SELECT random() FROM generate_series(1, 100000)));-- 执行时间:4.3秒(提升530倍)

性能对比结果(生产环境数据):

指标

MySQL 8.0

PostgreSQL 15

提升倍数

单特征更新

23ms

0.04ms

575x

批量更新10万

38分钟

4.3秒

530x

特征查询(1000用户)

1.8秒

12ms

150x

存储空间

1.2TB

680GB

1.8x(压缩)

3 A/B测试框架的SQL化改造

MySQL方案(应用层逻辑):

# Python代码实现测试分组def assign_test_group(user_id):    cursor.execute("SELECT user_id FROM experiment_groups WHERE user_id = %s", (user_id,))    if cursor.fetchone():        return cursor.fetchone()['group_name']        group = 'A' if hash(user_id) % 100 < 50 else 'B'    cursor.execute("INSERT INTO experiment_groups VALUES (%s, %s)", (user_id, group))    return group

PostgreSQL方案(数据库层函数):

-- 创建确定性哈希函数CREATE OR REPLACE FUNCTION stable_hash(input TEXT)RETURNS INTEGER AS $$    SELECT ('x' || substr(md5(input), 1, 8))::bit(32)::int;$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;-- 测试分组函数CREATE OR REPLACE FUNCTION get_experiment_group(    p_user_id INTEGER,    p_experiment_id TEXT,    p_allocation JSONB -- {'A': 50, 'B': 30, 'C': 20}) RETURNS TEXT AS $$DECLARE    user_hash INTEGER;    cumulative INTEGER := 0;    group_name TEXT;    group_percent INTEGER;BEGIN    user_hash := abs(stable_hash(p_experiment_id || p_user_id::TEXT)) % 100;        FOR group_name, group_percent IN         SELECT key, value::INTEGER         FROM jsonb_each_text(p_allocation)    LOOP        cumulative := cumulative + group_percent;        IF user_hash < cumulative THEN            RETURN group_name;        END IF;    END LOOP;        RETURN 'control';END;$$ LANGUAGE plpgsql IMMUTABLE;-- 使用示例SELECT     user_id,    get_experiment_group(user_id, 'homepage_redesign', '{"A": 50, "B": 25, "C": 25}') AS test_groupFROM active_usersWHERE user_id BETWEEN 1 AND 10000;-- 索引支持CREATE INDEX idx_experiment_lookup ON active_users USING btree (get_experiment_group(user_id, 'homepage_redesign', '{"A": 50, "B": 25, "C": 25}'));

性能提升: 数据库层分组将服务端计算耗时从45ms降至0.3ms,支持每秒30万+用户分组查询。


VI. 综合决策框架与最佳实践

策树:何时选择PostgreSQL

[PostgreSQL]MySQL vs PostgreSQL:算法工程师为何转投PostgreSQL阵营
image.png

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

683

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

323

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

348

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1096

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

358

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

697

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

575

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

417

2024.04.29

Java编译相关教程合集
Java编译相关教程合集

本专题整合了Java编译相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.8万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 805人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号