
# 数据库性能
- 业务禁止出现任何全表扫描的查询。
- 执行查询时，只选择需要返回的字段，不需要的字段不要返回。从而减少网络和进程处理的负载，修改数据时，只修改变化需要修改的字段，不要整个对象直接存储全部修改。
- 避免使用$not。GeminiDB Mongo并不会对缺失的数据进行索引，因此$not的查询条件将会要求在一个结果集中扫描所有记录。如果$not是唯一的查询条件，会对集合进行全表扫描。
- 用$and时把匹配最少结果的条件放在最前面，用$or时把匹配最多结果的条件放在最前面。
- 单个实例中，数据库的总的个数不要超过200个，总的集合个数不要超过500个。集合数量过多会导致内存压力变高，并且集合数量多会导致重启以及主备倒换性能变差，影响紧急情况下的高可用性能。
- 业务上线前，一定要对数据库进行性能压测，评估业务峰值场景下，对数据库的负载情况。
- 禁止同时执行大量并发事务，且长时间不提交。
- 业务正式上线前， 所有的查询类别，都应该先执行查询计划检查查询性能。 开发过程中，对集合的每一个操作都要通过执行explain()检查其执行计划。
  例如：
  **db.T_DeviceData.find({"deviceId" : "ae4b5769-896f"}).explain();**
  **db.T_DeviceData.find({"deviceId" : "77557c2-31b4"}).explain("executionStats");**
  对于查询而言，因为覆盖查询不需要读取文档，而是直接从索引中返回结果，这样的查询非常高效，所以尽可能使用索引覆盖查询。如果explain()的输出显示indexOnly字段为真，则说明这个查询就被一个索引覆盖。
  执行计划解析：
  - 看执行时间：executionStats.executionStages.executionTimeMillisEstimate和executionStats.executionStages.inputStage. executionTimeMillisEstimate时间越短越好。
    - executionStats.executionTimeMillis表示执行计划选择和执行的所有时间。
    
    - executionStats.executionStages.executionTimeMillisEstimate表示最优执行计划的执行完成时间。
    
    - executionStats.executionStages.inputStage. executionTimeMillisEstimate表示最优执行计划下的子阶段执行完成时间。
     
  
  - 看扫描条数（三个条目相同为最佳）
    - executionStats. nReturned表示匹配查询条件的文档数。
    
    - executionStats .totalKeysExamined表示索引扫描条目数。
    
    - executionStats .totalDocsExamined表示文档扫描条目数。
     
  
  - 看Stage状态(性能较好的Stage状态组合)
    - Fetch+IDHACK
    
    - Fetch+ixscan
    
    - Limit+（Fetch+ixscan）
    
    - PROJECTION+ixscan
    
    
    表1状态说明 
    | **状态名称**   | **描述**       |
    |:---|:---|
    | COLLSCAN   | 全表扫描         |
    | SORT       | 内存中进行排序      |
    | IDHACK     | 根据_id进行查询    |
    | TEXT       | 全文索引         |
    | COUNTSCAN  | 未用索引计数       |
    | FETCH      | 索引扫描         |
    | LIMIT      | 使用Limit限制返回数 |
    | SUBPLA     | 未用索引的$or查询阶段 |
    | PROJECTION | 使用索引计数       |
    | COUNT_SCAN | 使用索引计数       |
       
    
   
 
