PostgreSQL 对IN,EXISTS,ANY/ALL,JOIN的sql优化方案

测试环境:

postgres=# select version();
                         version
---------------------------------------------------------------------------------------------------------
 PostgreSQL 11.9 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)
postgres=#

数据准备:

$ pgbench -i -s 10
postgres=# \d
       List of relations
 Schema |    Name    | Type | Owner
--------+------------------+-------+----------
 public | pgbench_accounts | table | postgres
 public | pgbench_branches | table | postgres
 public | pgbench_history | table | postgres
 public | pgbench_tellers | table | postgres
(4 rows)

postgres=# select * from pgbench_accounts limit 1;
 aid | bid | abalance |                    filler
-----+-----+----------+--------------------------------------------------------------------------------------
  1 |  1 |    0 |
(1 row)

postgres=# select * from pgbench_branches limit 1;
 bid | bbalance | filler
-----+----------+--------
  1 |    0 |
(1 row)

postgres=# select * from pgbench_history limit 1;
 tid | bid | aid | delta | mtime | filler
-----+-----+-----+-------+-------+--------
(0 rows)

postgres=# select * from pgbench_tellers limit 1;
 tid | bid | tbalance | filler
-----+-----+----------+--------
  1 |  1 |    0 |
(1 row)

postgres=# select * from pgbench_branches;
 bid | bbalance | filler
-----+----------+--------
  1 |    0 |
  2 |    0 |
  3 |    0 |
  4 |    0 |
  5 |    0 |
  6 |    0 |
  7 |    0 |
  8 |    0 |
  9 |    0 |
 10 |    0 |
(10 rows)

postgres=# update pgbench_branches set bbalance=4500000 where bid in (4,7);
UPDATE 2
postgres=#

IN语句

查询要求:找出那些余额(balance)大于0的每个分支(branch)在表在pgbench_accounts中有多少个账户

1.使用IN子句 

SELECT
  count( aid ),bid
FROM
  pgbench_accounts
WHERE
  bid IN ( SELECT bid FROM pgbench_branches WHERE bbalance > 0 )
GROUP BY
  bid;
 

2.使用ANY子句

SELECT
  count( aid ),bid
FROM
  pgbench_accounts
WHERE
  bid = ANY ( SELECT bid FROM pgbench_branches WHERE bbalance > 0 )
GROUP BY
  bid;

  

3.使用EXISTS子句

SELECT
  count( aid ),bid
FROM
  pgbench_accounts
WHERE
  EXISTS ( SELECT bid FROM pgbench_branches WHERE bbalance > 0 AND pgbench_accounts.bid = pgbench_branches.bid )
GROUP BY
  bid;

  

4.使用INNER JOIN

SELECT
  count( aid ),a.bid
FROM
  pgbench_accounts a
  JOIN pgbench_branches b ON a.bid = b.bid
WHERE
  b.bbalance > 0
GROUP BY
  a.bid;

在完成这个查询要求的时候,有人可能会假设exists和inner join性能可能会更好,因为他们可以使用两表连接的逻辑和优化。而IN和ANY子句需要使用子查询。

然而,PostgreSQL(10版本之后)已经智能的足以对上面四种写法产生相同的执行计划!

所有上面的写法都会产生相同的执行计划:

                                      QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Finalize GroupAggregate (cost=23327.73..23330.26 rows=10 width=12) (actual time=97.199..99.014 rows=2 loops=1)
  Group Key: a.bid
  -> Gather Merge (cost=23327.73..23330.06 rows=20 width=12) (actual time=97.191..99.006 rows=6 loops=1)
     Workers Planned: 2
     Workers Launched: 2
     -> Sort (cost=22327.70..22327.73 rows=10 width=12) (actual time=93.762..93.766 rows=2 loops=3)
        Sort Key: a.bid
        Sort Method: quicksort Memory: 25kB
        Worker 0: Sort Method: quicksort Memory: 25kB
        Worker 1: Sort Method: quicksort Memory: 25kB
        -> Partial HashAggregate (cost=22327.44..22327.54 rows=10 width=12) (actual time=93.723..93.727 rows=2 loops=3)
           Group Key: a.bid
           -> Hash Join (cost=1.14..22119.10 rows=41667 width=8) (actual time=24.024..83.263 rows=66667 loops=3)
              Hash Cond: (a.bid = b.bid)
              -> Parallel Seq Scan on pgbench_accounts a (cost=0.00..20560.67 rows=416667 width=8) (actual time=0.023..43.151 rows=333333 loops=3)
              -> Hash (cost=1.12..1.12 rows=1 width=4) (actual time=0.027..0.028 rows=2 loops=3)
                 Buckets: 1024 Batches: 1 Memory Usage: 9kB
                 -> Seq Scan on pgbench_branches b (cost=0.00..1.12 rows=1 width=4) (actual time=0.018..0.020 rows=2 loops=3)
                    Filter: (bbalance > 0)
                    Rows Removed by Filter: 8
 Planning Time: 0.342 ms
 Execution Time: 99.164 ms
(22 rows)

那么,我们是否可以得出这样的结论:我们可以随意地编写查询,而PostgreSQL的智能将会处理其余的问题?!

等等!

如果我们考虑排除情况,事情会变得不同。

排除查询

查询要求:找出那些余额(balance)不大于0的每个分支(branch)在表在pgbench_accounts中有多少个账户

1.使用NOT IN

SELECT
  count( aid ),bid
FROM
  pgbench_accounts
WHERE
  bid NOT IN ( SELECT bid FROM pgbench_branches WHERE bbalance > 0 )
GROUP BY
  bid;

执行计划:

                                    QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------
 Finalize GroupAggregate (cost=23645.42..23647.95 rows=10 width=12) (actual time=128.606..130.502 rows=8 loops=1)
  Group Key: pgbench_accounts.bid
  -> Gather Merge (cost=23645.42..23647.75 rows=20 width=12) (actual time=128.598..130.490 rows=24 loops=1)
     Workers Planned: 2
     Workers Launched: 2
     -> Sort (cost=22645.39..22645.42 rows=10 width=12) (actual time=124.960..124.963 rows=8 loops=3)
        Sort Key: pgbench_accounts.bid
        Sort Method: quicksort Memory: 25kB
        Worker 0: Sort Method: quicksort Memory: 25kB
        Worker 1: Sort Method: quicksort Memory: 25kB
        -> Partial HashAggregate (cost=22645.13..22645.23 rows=10 width=12) (actual time=124.917..124.920 rows=8 loops=3)
           Group Key: pgbench_accounts.bid
           -> Parallel Seq Scan on pgbench_accounts (cost=1.13..21603.46 rows=208333 width=8) (actual time=0.078..83.134 rows=266667 loops=3)
              Filter: (NOT (hashed SubPlan 1))
              Rows Removed by Filter: 66667
              SubPlan 1
               -> Seq Scan on pgbench_branches (cost=0.00..1.12 rows=1 width=4) (actual time=0.020..0.021 rows=2 loops=3)
                  Filter: (bbalance > 0)
                  Rows Removed by Filter: 8
 Planning Time: 0.310 ms
 Execution Time: 130.620 ms
(21 rows)

postgres=#

2.使用<>ALL

SELECT
  count( aid ),bid
FROM
  pgbench_accounts
WHERE
  bid <> ALL ( SELECT bid FROM pgbench_branches WHERE bbalance > 0 )
GROUP BY
  bid;

执行计划:

                                     QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------
 Finalize GroupAggregate (cost=259581.79..259584.32 rows=10 width=12) (actual time=418.220..419.913 rows=8 loops=1)
  Group Key: pgbench_accounts.bid
  -> Gather Merge (cost=259581.79..259584.12 rows=20 width=12) (actual time=418.212..419.902 rows=24 loops=1)
     Workers Planned: 2
     Workers Launched: 2
     -> Sort (cost=258581.76..258581.79 rows=10 width=12) (actual time=413.906..413.909 rows=8 loops=3)
        Sort Key: pgbench_accounts.bid
        Sort Method: quicksort Memory: 25kB
        Worker 0: Sort Method: quicksort Memory: 25kB
        Worker 1: Sort Method: quicksort Memory: 25kB
        -> Partial HashAggregate (cost=258581.50..258581.60 rows=10 width=12) (actual time=413.872..413.875 rows=8 loops=3)
           Group Key: pgbench_accounts.bid
           -> Parallel Seq Scan on pgbench_accounts (cost=0.00..257539.83 rows=208333 width=8) (actual time=0.054..367.244 rows=266667 loops=3)
              Filter: (SubPlan 1)
              Rows Removed by Filter: 66667
              SubPlan 1
               -> Materialize (cost=0.00..1.13 rows=1 width=4) (actual time=0.000..0.001 rows=2 loops=1000000)
                  -> Seq Scan on pgbench_branches (cost=0.00..1.12 rows=1 width=4) (actual time=0.001..0.001 rows=2 loops=337880)
                     Filter: (bbalance > 0)
                     Rows Removed by Filter: 8
 Planning Time: 0.218 ms
 Execution Time: 420.035 ms
(22 rows)
postgres=#

3.使用NOT EXISTS

SELECT
  count( aid ),bid
FROM
  pgbench_accounts
WHERE
  NOT EXISTS ( SELECT bid FROM pgbench_branches WHERE bbalance > 0 AND pgbench_accounts.bid = pgbench_branches.bid )
GROUP BY
  bid;

执行计划:

                                      QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------
 Finalize GroupAggregate (cost=28327.72..28330.25 rows=10 width=12) (actual time=152.024..153.931 rows=8 loops=1)
  Group Key: pgbench_accounts.bid
  -> Gather Merge (cost=28327.72..28330.05 rows=20 width=12) (actual time=152.014..153.917 rows=24 loops=1)
     Workers Planned: 2
     Workers Launched: 2
     -> Sort (cost=27327.70..27327.72 rows=10 width=12) (actual time=147.782..147.786 rows=8 loops=3)
        Sort Key: pgbench_accounts.bid
        Sort Method: quicksort Memory: 25kB
        Worker 0: Sort Method: quicksort Memory: 25kB
        Worker 1: Sort Method: quicksort Memory: 25kB
        -> Partial HashAggregate (cost=27327.43..27327.53 rows=10 width=12) (actual time=147.732..147.737 rows=8 loops=3)
           Group Key: pgbench_accounts.bid
           -> Hash Anti Join (cost=1.14..25452.43 rows=375000 width=8) (actual time=0.134..101.884 rows=266667 loops=3)
              Hash Cond: (pgbench_accounts.bid = pgbench_branches.bid)
              -> Parallel Seq Scan on pgbench_accounts (cost=0.00..20560.67 rows=416667 width=8) (actual time=0.032..45.174 rows=333333 loops=3)
              -> Hash (cost=1.12..1.12 rows=1 width=4) (actual time=0.036..0.037 rows=2 loops=3)
                 Buckets: 1024 Batches: 1 Memory Usage: 9kB
                 -> Seq Scan on pgbench_branches (cost=0.00..1.12 rows=1 width=4) (actual time=0.025..0.027 rows=2 loops=3)
                    Filter: (bbalance > 0)
                    Rows Removed by Filter: 8
 Planning Time: 0.322 ms
 Execution Time: 154.040 ms
(22 rows)
postgres=#

4.使用LEFT JOIN和IS NULL

SELECT
  count( aid ),a.bid
FROM
  pgbench_accounts a
  LEFT JOIN pgbench_branches b ON a.bid = b.bid AND b.bbalance > 0
WHERE
  b.bid IS NULL
GROUP BY
  a.bid;

执行计划:

                                      QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Finalize GroupAggregate (cost=28327.72..28330.25 rows=10 width=12) (actual time=145.298..147.096 rows=8 loops=1)
  Group Key: a.bid
  -> Gather Merge (cost=28327.72..28330.05 rows=20 width=12) (actual time=145.288..147.083 rows=24 loops=1)
     Workers Planned: 2
     Workers Launched: 2
     -> Sort (cost=27327.70..27327.72 rows=10 width=12) (actual time=141.883..141.887 rows=8 loops=3)
        Sort Key: a.bid
        Sort Method: quicksort Memory: 25kB
        Worker 0: Sort Method: quicksort Memory: 25kB
        Worker 1: Sort Method: quicksort Memory: 25kB
        -> Partial HashAggregate (cost=27327.43..27327.53 rows=10 width=12) (actual time=141.842..141.847 rows=8 loops=3)
           Group Key: a.bid
           -> Hash Anti Join (cost=1.14..25452.43 rows=375000 width=8) (actual time=0.087..99.535 rows=266667 loops=3)
              Hash Cond: (a.bid = b.bid)
              -> Parallel Seq Scan on pgbench_accounts a (cost=0.00..20560.67 rows=416667 width=8) (actual time=0.025..44.337 rows=333333 loops=3)
              -> Hash (cost=1.12..1.12 rows=1 width=4) (actual time=0.026..0.027 rows=2 loops=3)
                 Buckets: 1024 Batches: 1 Memory Usage: 9kB
                 -> Seq Scan on pgbench_branches b (cost=0.00..1.12 rows=1 width=4) (actual time=0.019..0.020 rows=2 loops=3)
                    Filter: (bbalance > 0)
                    Rows Removed by Filter: 8
 Planning Time: 0.231 ms
 Execution Time: 147.180 ms
(22 rows)
postgres=#

NOT IN 和 <> ALL生成执行计划都包含了一个子查询。他们是各自独立的。

而NOT EXISTS和LEFT JOIN生成了相同的执行计划。

这些hash连接(或hash anti join)是完成查询要求的最灵活的方式。这也是推荐exists或join的原因。因此,推荐使用exists或join的经验法则是有效的。

但是,我们继续往下看! 即使有了子查询执行计划,NOT IN子句的执行时间也会更好?

是的。PostgreSQL做了出色的优化,PostgreSQL将子查询计划进行了hash处理。因此PostgreSQL对如何处理IN子句有了更好的理解,这是一种逻辑思维方式,因为很多人倾向于使用IN子句。子查询返回的行很少,但即使子查询返回几百行,也会发生同样的情况。

但是,如果子查询返回大量行(几十万行)怎么办?让我们尝试一个简单的测试:

CREATE TABLE t1 AS
SELECT * FROM generate_series(0, 500000) id;

CREATE TABLE t2 AS
SELECT (random() * 4000000)::integer id
FROM generate_series(0, 4000000);

ANALYZE t1;
ANALYZE t2;

EXPLAIN SELECT id
FROM t1
WHERE id NOT IN (SELECT id FROM t2);

执行计划:

    QUERY PLAN
--------------------------------------------------------------------------------
 Gather (cost=1000.00..15195064853.01 rows=250000 width=4)
  Workers Planned: 1
  -> Parallel Seq Scan on t1 (cost=0.00..15195038853.01 rows=147059 width=4)
     Filter: (NOT (SubPlan 1))
     SubPlan 1
      -> Materialize (cost=0.00..93326.01 rows=4000001 width=4)
         -> Seq Scan on t2 (cost=0.00..57700.01 rows=4000001 width=4)
(7 rows)

postgres=#

这里,执行计划将子查询进行了物化。代价评估变成了15195038853.01。(PostgreSQL的默认设置,如果t2表的行低于100k,会将子查询进行hash)。这样就会严重影响性能。因此,对于那种子查询返回的行数很少的场景,IN子句可以起到很好的作用。

其它注意点

有的!在我们用不同的方式写查询的时候,可能有数据类型的转换。

比如,语句:

EXPLAIN ANALYZE SELECT * FROM emp WHERE gen = ANY(ARRAY['M', 'F']);

就会发生隐式的类型转换:

Seq Scan on emp (cost=0.00..1.04 rows=2 width=43) (actual time=0.023..0.026 rows=3 loops=1)
 Filter: ((gen)::text = ANY ('{M,F}'::text[]))

这里的(gen)::text就发生了类型转换。如果在大表上,这种类型转换的代价会很高,因此,PostgreSQL对IN子句做了更好的处理。

EXPLAIN ANALYZE SELECT * FROM emp WHERE gen IN ('M','F');

 Seq Scan on emp (cost=0.00..1.04 rows=3 width=43) (actual time=0.030..0.034 rows=3 loops=1)
  Filter: (gen = ANY ('{M,F}'::bpchar[]))

将IN子句转换成了ANY子句,没有对gen列进行类型转换。而是将M\F转成了bpchar(内部等价于char)

总结

简单来说,exists和直接join表通常比较好。

很多情况下,PostgreSQL将IN子句换成被hash的子计划。在一些特殊场景下,IN可以获得更好的执行计划。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • postgresql 实现启动、状态查看、关闭

    利用psql启动数据库 [postgres@highgo ~]$ pg_ctl start 查看系统中运行的postgres进程 #ps -ef | grep postgres 连接postgresql数据库 #psql -h 127.0.0.1 -d postgres -U postgres 停止postgresql数据库实例 #pg_ctl stop #ps -ef | grep postgres 启动服务器最简单的方法是像下面这样: $ postgres -D /usr/local/pgs

  • postgresql连续归档及时间点恢复的操作

    简介 前面我们介绍了通过pgsql的流复制在生产环境中搭建高可用环境来保证服务的可持续性:我们也要对数据库进行周期备份,来防止数据的丢失,这就需要连续归档,它不仅可以用于大型数据库的增量备份和恢复,也可以用于搭建standby镜像备份.    PostgreSQL默认处于非归档模式.开启归档模式,主要涉及到三个参数:wal_level,archive_mode和archive_commandwal_level参数默认为mininal,设置此参数为archive或者之上的级别都可以打开归档.当po

  • postgresql修改完端口后直接psql连接数据库报错的解决

    今天修改pg的端口号port改成5435后重启完数据库的时候直接psql进库的时候进不去 [postgres@node2 data]$ psql psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.PGSQL.5432 这时,进数据库有两种方式 1.psq

  • 浅谈PostgreSQL中的孤儿文件用法(orphaned data files)

    创建一个测试表 postgres=# create table t1(a int); CREATE TABLE postgres=# select pg_relation_filepath('t1'); pg_relation_filepath ---------------------- base/75062/75297 (1 row) postgres=# 在操作系统上已经可以看到该文件. $ ls -la $PGDATA/base/75062/75297 -rw------- 1 post

  • PostgreSQL 启动失败的解决方案

    环境 Red Hat CloudForms 4.x 问题 postgresql 启动失败,并导致evmserverd崩溃. [----] I, [2016-11-29T03:12:31.816753 #1201:e4f994] INFO -- : MIQ(PostgresAdmin.runcmd_with_logging) Running command... service rh-postgresql94-postgresql start [----] E, [2016-11-29T03:12

  • 解决postgresql无法远程访问的情况

    今天刚入手这个数据库玩玩,发现无法通过IP去访问数据库,后面查询原因为,该数据库默认只能通过本地连接,也就是回环地址(127.0.0.1) 解决方案: 1.修改安装目录下的data\pg_hba.conf,在配置文件最后有IPV4和IPV6的配置,新增一行(这里我用的IPV4,开放所有IP) host all all 0.0.0.0/0 md5 说明: 该配置为允许所有IP访问,下面有对应的一些配置示例提供参考 32 -> 192.168.1.1/32 表示必须是来自这个IP地址的访问才合法:

  • 浅谈Postgresql默认端口5432你所不知道的一点

    关于Postgresql端口5432的定义: 5432端口,已经在IANA(The Internet Assigned Numbers Authority,互联网数字分配机构)注册, 并把该端口唯一分配给Postgres. 这意味着,一台安装了linux OS的服务器,哪怕没有安装过postgresql数据库,也会有这个预留端口. 查看这个预留端口的方法如下: new@newdb-> cat /etc/services |grep 5432 postgres 5432/tcp postgresq

  • 解决postgresql insert into select无法使用并行查询的问题

    本文信息基于PG13.1. 从PG9.6开始支持并行查询.PG11开始支持CREATE TABLE - AS.SELECT INTO以及CREATE MATERIALIZED VIEW的并行查询. 先说结论: 换用create table as 或者select into或者导入导出. 首先跟踪如下查询语句的执行计划: select count(*) from test t1,test1 t2 where t1.id = t2.id ; postgres=# explain analyze se

  • PostgreSQL 对IN,EXISTS,ANY/ALL,JOIN的sql优化方案

    测试环境: postgres=# select version(); version --------------------------------------------------------------------------------------------------------- PostgreSQL 11.9 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-b

  • postgresql 数据库 与TimescaleDB 时序库 join 在一起

    之前在CSDN阅读资料时,发现有人问怎么把 postgresql数据库 的表 跟TimescaleDB 时序库的表 join在一起,正好我在查询数据的时候遇到过这个问题 ,我说一下我的解决方案 我选择的是postgresql数据库的fdw功能(postgres_fdw插件) ** 一 安装postgres_fdw插件 1.1安装postgres_fdw插件 ** su – postgres -bash-4.2$ psql postgres=# \c hrmwv2 #(数据库名字) Create

  • sql优化实战 把full join改为left join +union all(从5分钟降为10秒)

    今天收到一个需求,要改写一个报表的逻辑,当改完之后,再次运行,发现运行超时. 因为特殊原因,无法访问客户的服务器,没办法查看sql的执行计划.没办法知道表中的索引情况,所以,尝试从语句的改写上来优化. 一.原始语句如下: select isnull(vv.customer_id,v.customer_id) as customer_id, isnull(vv.business_date,replace(v.business_date,'-','')) as business_date, v.pr

  • MySQL中join语句怎么优化

    目录 Simple Nested-Loop Join Block Nested-Loop Join Index Nested-Loop Join 如何选择驱动表? Simple Nested-Loop Join 我们来看一下当进行 join 操作时,mysql是如何工作的.常见的 join 方式有哪些? 如图,当我们进行连接操作时,左边的表是驱动表,右边的表是被驱动表 Simple Nested-Loop Join 这种连接操作是从驱动表中取出一条记录然后逐条匹配被驱动表的记录,如果条件匹配则将

  • SQL语句优化之JOIN和LEFT JOIN 和 RIGHT JOIN语句的优化

    在数据库的应用中,我们经常需要对数据库进行多表查询,然而当数据量非常大时多表查询会对执行效率产生非常大的影响,因此我们在使用JOIN和LEFT JOIN 和 RIGHT JOIN语句时要特别注意: SQL语句的join原理: 数据库中的join操作,实际上是对一个表和另一个表的关联,而很多错误理解为,先把这两个表来一个迪卡尔积,然后扔到内存,用where和having条件来慢慢筛选,其实数据库没那么笨的,那样会占用大量的内存,而且效率不高,比如,我们只需要的一个表的一些行和另一个表的一些行,如果

  • Postgresql psql文件执行与批处理多个sql文件操作

    新建一个批处理文件batch.sql \encoding UTF8; \cd C:/Gmind/ddl \set ON_ERROR_STOP 1 \set ECHO all \timing on \i s_product.sql; \i s_branch.sql; \i s_comment.sql; \i s_class.sql; \i s_drawing.sql; \i s_dmemo.sql; \i s_form.sql; \encoding 设置客户端字符集编码(可选) \cd 切换目录.

  • PostgreSQL 慢查询SQL跟踪操作

    PostgreSQL 开启慢SQL捕获在排查问题时是个很有效的手段.根据慢SQL让我在工作中真正解决了实际问题,很有帮助. PostgreSQL 日志支持的输出格式有 stderr(默认).csvlog .syslog 一般的错误跟踪,只需在配置文件 [postgresql.conf]简单设置几个参数,当然还有错误级别等要设置. logging_collector = on log_destination = 'stderr' log_directory = 'log' log_filename

  • Oracle SQL tuning 数据库优化步骤分享(图文教程)

    SQL Turning 是Quest公司出品的Quest Central软件中的一个工具.Quest Central是一款集成化.图形化.跨平台的数据库管理解决方案,可以同时管理 Oracle.DB2 和 SQL server 数据库. 一.SQL Tuning for SQL Server简介 SQL语句的优化对发挥数据库的最佳性能非常关键.然而不幸的是,应用优化通常由于时间和资源的因素而被忽略.SQL Tuning (SQL优化)模块可以对比和评测特定应用中SQL语句的运行性能,提出智能化的

  • 详解MySQL数据库千万级数据查询和存储

    百万级数据处理方案 数据存储结构设计 表字段设计 表字段 not null,因为 null 值很难查询优化且占用额外的索引空间,推荐默认数字 0. 数据状态类型的字段,比如 status, type 等等,尽量不要定义负数,如 -1.因为这样可以加上 UNSIGNED,数值容量就会扩大一倍. 可以的话用 TINYINT.SMALLINT 等代替 INT,尽量不使用 BIGINT,因为占的空间更小. 字符串类型的字段会比数字类型占的空间更大,所以尽量用整型代替字符串,很多场景是可以通过编码逻辑来实

  • MySQL索引优化实例分析

    目录 1.数据准备 2.实例一 3.MySQL如何选择合适的索引? 4.常见 SQL 深入优化 4.1.Order by与Group by优化 4.2.分页查询优化 4.3.join关联查询优化 4.3.1.数据准备 4.3.2.MySQL 表关联常见的两种算法 4.4.in和exsits优化 4.5.count(*)查询优化 5.索引设计原则 1.数据准备 #1.建立员工表,并创建name,age,position索引,id为自增主键 CREATE TABLE `employees` (  `

随机推荐