
# 如何通过SQL优化来提升DDS性能
文档数据库属于NoSQL数据库，提供了可扩展的高性能数据解决方案，与关系型数据库（例如MySQL、SQLServer、Oracle）一样，在数据库设计、语句优化、索引创建等方面都会影响数据库的使用性能。
下面从不同维度，给出提升DDS使用性能的建议：
#### 数据库和集合的创建
1. 使用**短字段名**，以节约存储空间。文档数据库与关系型数据库不同，集合中的每个文档都存储字段名，使用短字段名可以有效的节约存储空间。
2. 有效地控制集合中的文档数量，避免影响查询性能。如果有必要，可以进行定期归档。
3. 每条文档都提供默认的"_id"值，**禁止向** **"_id"** **中保存自定义值**。
4. **固定集合**相较其他集合，插入速度快，并且能够自动删除旧数据。用户可以根据业务需要，选择创建固定集合以提高性能。
更多规范建议请参见《文档数据库服务开发指南》中"[使用规范](https://support.huaweicloud.com/usermanual-dds/dds_taps_0002.html)"章节。
#### 查询操作
**索引**
1. 根据业务需求，对经常查询的数据字段创建适当的索引。需注意，索引会占用一些空间，并且插入操作和索引更新会消耗资源。因此，建议每个集合的索引数量不超过5个。 案例：出现数据查询缓慢，如果没有创建索引，建议对经常查询的数据字段创建适当的索引，优化查询速度。
   
2. 对于包含多个键的查询，建议创建包含这些键的复合索引。复合索引的键值顺序很关键，需遵循索引最左前缀原则，查询应包含最左索引字段，以索引创建顺序为准，与查询字段顺序无关。
3. 给索引添加TTL属性，自动筛选过期文档并删除。创建TTL的索引必须是日期类型。TTL索引是单字段索引，而非复合索引。
4. 需要在集合中某个字段上创建索引，但当集合中大量文档不包含该键值时，建议创建稀疏索引。
5. 创建文本索引时，字段指定text，而不是1或者-1。每个集合只有一个文本索引，但它可以为任意多个字段建立索引。
**命令使用**
1. 使用findOne方法，在数据库中查询匹配多个项目，将会在自然排序文件集合中返回第一个项目。如果需要返回多个文档，则使用find方法。
2. 如果查询无需返回整个文档，或只是用来判断键值是否存在，可以通过投影$project来限制返回字段，减少网络流量和客户端的内存使用。
3. 除了前缀样式查询，正则表达式查询执行的时间比大多数选择器更久，不建议使用索引。
4. 查询中的某些含"$"的操作符可能会降低使用性能。在业务中尽量不要使用该类操作符：$or、$nin、$not、$ne、$exists。
   ![](https://support.huaweicloud.com/bestpractice-dds/public_sys-resources/note_3.0-zh-cn.png)
   - $or：有多少个条件就会查询多少次，最后合并结果集，建议替换为$in。
   
   - $nin：可能会匹配到大多数的索引，此时，查询优化器会退化为全表扫描。
   
   - $not：可能会导致查询优化器无法匹配到具体的索引，退化为全表扫描。
   
   - $ne：选择字段值不等于指定值的文档，如果多数为取相反值的文档，将会扫描整个索引。
   
   - $exists：对于松散的文档结构，查询必须遍历每一个文档。
   
   
   更多信息，请参见[MongoDB官方文档](https://www.mongodb.com/zh-cn/docs/v4.4/reference/operator/query/)。
   
 
**注意事项**
1. 操作符$where和$exists中不能使用索引。
2. 如果查询结果需要排序，尽量控制结果集的数量。
3. 涉及多个字段的索引时，尽量将用于精确匹配的字段放在索引的前面。
4. 如果查询条件中的键值顺序和复合索引中的创建顺序不一致，DDS会自动优化为查询跟索引顺序一致。
   - 修改操作 通过操作符对文档进行修改，通常可以获得更好的性能。该方式不需要往返服务器来获取并修改文档数据，在序列化和传输数据上花费更少的时间。
     
   
   - 批量插入 批量插入（batchInsert）可以减少数据向服务器的提交次数，提高使用性能。批量提交的数据的BSON Size不超过48MB。
     
   
   - 聚合运算 聚合运算中，$match需前置于$group，减少$group操作符要处理的文档数量。
     
    
 
