V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
TangMonk
V2EX  ›  问与答

PostgreSQL 1000W 条数据,执行 SELECT 查询,很缓慢,如何优化?

  •  
  •   TangMonk · 2017-07-23 19:41:29 +08:00 · 8850 次点击
    这是一个创建于 2681 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我帮我朋友做了个 iOS 关于定位的 app 后端, 用 NodeJS 来做的 http api, PostgreSQL 来做的数据存储。

    现在用户量上来了,经纬度数据有 1000W 条了, 每分钟最多有 400 个请求。

    数据库表结构:

    location=# \d locations
                                       Table "public.locations"
      Column   |           Type           |                       Modifiers
    -----------+--------------------------+--------------------------------------------------------
     id        | integer                  | not null default nextval('locations_id_seq'::regclass)
     phone     | text                     | not null
     longitude | text                     | not null
     latitude  | text                     | not null
     date      | text                     | not null
     createdAt | timestamp with time zone |
     updatedAt | timestamp with time zone |
    Indexes:
        "locations_pkey" PRIMARY KEY, btree (id)
        "createdAt_idx" btree ("createdAt")
        "phone_idx" btree (phone)
    

    执行查询:

    location=# EXPLAIN ANALYZE select * from "locations" where "phone" = '15828354000' order by "createdAt" desc limit 1;
                                                                            QUERY PLAN
    -----------------------------------------------------------------------------------------------------------------------------------------------------------
     Limit  (cost=0.43..5.22 rows=1 width=74) (actual time=4848.720..4848.720 rows=1 loops=1)
       ->  Index Scan Backward using "createdAt_idx" on locations  (cost=0.43..663383.70 rows=138739 width=74) (actual time=4848.718..4848.718 rows=1 loops=1)
             Filter: (phone = '15828354000'::text)
             Rows Removed by Filter: 2032111
     Planning time: 0.109 ms
     Execution time: 4848.746 ms
    

    也就是说没次用户查询一次他最近的位置都会耗时 4.8s

    我在想要不要用 Redis 来对这个接口做个缓存呢?

    10 条回复    2017-07-24 09:03:59 +08:00
    mansur
        1
    mansur  
       2017-07-23 19:49:56 +08:00   ❤️ 1
    难道 phone 上没索引?有索引会很快呀,怎么会 4.8 秒?
    mansur
        2
    mansur  
       2017-07-23 19:51:06 +08:00
    平均每个 phone 有多少条数据?
    lujjjh
        3
    lujjjh  
       2017-07-23 19:58:07 +08:00   ❤️ 1
    需要建立 phone, createdAt 的联合索引
    stabc
        4
    stabc  
       2017-07-23 20:10:15 +08:00   ❤️ 1
    你这个表和查询应该都没有问题,哪怕每个用户有一万条记录,这个查询也应该毫秒级的。
    你监控一下硬盘读写吧,如果瓶颈在硬盘上。如果这样,首先看看服务器内存和数据量的比值多少,足够的话再看看配置文件,有没有充分利用内存。
    sagaxu
        5
    sagaxu  
       2017-07-23 20:22:39 +08:00   ❤️ 1
    缺个索引,(phone, createdAt desc)
    TangMonk
        6
    TangMonk  
    OP
       2017-07-23 20:31:35 +08:00
    @lujjjh
    @sagaxu

    谢谢,加了索引直接 0.046ms 了
    akrf
        7
    akrf  
       2017-07-23 21:31:11 +08:00 via Android
    十万倍的性能提升!
    julyclyde
        8
    julyclyde  
       2017-07-24 06:36:16 +08:00
    node 大大降低了入行门槛啊
    TangMonk
        9
    TangMonk  
    OP
       2017-07-24 07:27:10 +08:00 via Android
    @julyclyde node 要做好还是很难的
    akrf
        10
    akrf  
       2017-07-24 09:03:59 +08:00 via Android
    @julyclyde 哈哈哈,其实没有啦,后端开发很庞大的,所有程序员都要一点一点学习数据库等各种知识
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3708 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 05:04 · PVG 13:04 · LAX 21:04 · JFK 00:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.