Esta é a nossa entrega de março para Serviço de consultor de índices para o N1QL depois de corrigir alguns bugs encontrados após nossa última atualização em fevereiro. Planejamos continuar melhorando o serviço Index Advisor (O que é isso?). As correções no Index Advisor que você normalmente veria na próxima versão de manutenção agora estarão disponíveis para você todos os meses.
Para quem ele serve? e Quando você deve usá-lo?
https://index-advisor.couchbase.com/
Ao custo de me repetir,
Esse serviço fornecerá recomendações de índices para ajudar DBAs, desenvolvedores e arquitetos a otimizar o desempenho das consultas e atender aos SLAs.
Esse serviço será útil se você:
- Deseja evitar a leitura do criação de índices regrasCompreendê-los e implementá-los para encontrar os índices apropriados para sua consulta/consultas/carga de trabalho.
- Ainda não deseja fazer o download do servidor Couchbase 6.5 mais recente.
- Está usando um versão mais antiga do Couchbase (versão 5.5, 6.0) e precisa de ajuda para criar os índices certos para suas consultas.
- Deseja gerar conselhos para índices sem criar um bucket ou fazer upload do esquema ou dos dados.
O que há de novo?
Mesmo que você tenha feito o download do servidor Couchbase Server 6.5 e possa usar o Index Advisor do Query Workbench, esse Index Advisor é uma versão mais recente (sem uma interface de usuário de ótima aparência), mas com os seguintes defeitos corrigidos.
1.Index Advisor para suportar TTL (meta().expiration & meta.cas)
Com esse aprimoramento, uma consulta como
|
1 2 3 4 5 |
ADVISE SELECT META().id, META().expiration FROM `travel-sample` WHERE META().expiration = 0 ORDER BY META().id LIMIT 2; |
que costumava dar
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span style="color: #ff0000">{ "results": [ { "#operator": "Advise", "advice": { "#operator": "IndexAdvice", "adviseinfo": { "recommended_indexes": "No index recommendation at this time: no keyspace found." } }, "query": "SELECT name, META().id\nFROM `travel-sample`\nWHERE META().id > \"g\"\nLIMIT 2;" } ] }</span> |
agora dá
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<span style="color: #339966">{ "results": [ { "#operator": "Advise", "advice": { "#operator": "IndexAdvice", "adviseinfo": { "recommended_indexes": { "covering_indexes": [ { "index_statement": "CREATE INDEX adv_meta_self_expiration ON `travel-sample`(meta(self).`expiration`)", "keyspace_alias": "travel-sample" } ], "indexes": [ { "index_statement": "CREATE INDEX adv_meta_self_expiration ON `travel-sample`(meta(self).`expiration`)", "keyspace_alias": "travel-sample", "recommending_rule": "Index keys follow order of predicate types: 2. equality/null/missing." } ] } } }, "query": "SELECT META().id, META().expiration\nFROM `travel-sample`\nWHERE META().expiration = 0\nORDER BY META().id\nLIMIT 2;" } </span> <span style="color: #339966">] }</span> |
ou
|
1 2 3 4 5 |
ADVISE SELECT name, META().cas FROM `travel-sample` WHERE type="hotel" ORDER BY META().cas DESC LIMIT 2; |
que costumava dar:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<span style="color: #ff0000">{ "results": [ { "#operator": "Advise", "advice": { "#operator": "IndexAdvice", "adviseinfo": { "recommended_indexes": { "indexes": [ { "index_statement": "CREATE INDEX adv_type ON `travel-sample`(`type`)", "keyspace_alias": "travel-sample", "recommending_rule": "Index keys follow order of predicate types: 2. equality/null/missing." } ] } } }, "query": "SELECT name, META().cas FROM `travel-sample` WHERE type=\"hotel\" ORDER BY META().cas DESC LIMIT 2;" } ] }</span> |
agora dá
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<span style="color: #339966">{ "results": [ { "#operator": "Advise", "advice": { "#operator": "IndexAdvice", "adviseinfo": { "recommended_indexes": { "covering_indexes": [ { "index_property": "ORDER pushdown, LIMIT pushdown", "index_statement": "CREATE INDEX adv_type_meta_self_casDESC_name ON `travel-sample`(`type`,meta(self).`cas` DESC,`name`)", "keyspace_alias": "travel-sample" } ], "indexes": [ { "index_statement": "CREATE INDEX adv_type ON `travel-sample`(`type`)", "keyspace_alias": "travel-sample", "recommending_rule": "Index keys follow order of predicate types: 2. equality/null/missing." } ] } } }, "query": "SELECT name, META().cas\nFROM `travel-sample`\nWHERE type=\"hotel\"\nORDER BY META().cas DESC\nLIMIT 2;" } ] }</span> |
2. Aconselhar o ajuste da ordem das chaves de índice para predicados funcionais e de matriz
Esse defeito alterou ligeiramente as regras que tínhamos antes:
- Excluir a regra das chaves de índice funcional.
- Add rule “like” in the same position for scenario ” a like “%adv%”.This rule is applicable only when the pattern is of the type “%x”.If it is of the type “x%” the rule does not apply.
- As chaves de índice dos predicados funcionais seguem a ordem de EQ/in/LE/LT
Uma consulta como:
|
1 |
advise select * from shellTest where length(a21) <= 3 and c21 = 3 and c22 > 30 |
usado para dar
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span style="color: #ff0000">"results": [ { "#operator": "Advise", "advice": { "#operator": "IndexAdvice", "adviseinfo": { "recommended_indexes": { "indexes": [ { "index_statement": "CREATE INDEX adv_c21_c22_length_a21 ON `shellTest`(`c21`,`c22`,length((`a21`)))", "keyspace_alias": "shellTest", "recommending_rule": "Index keys follow order of predicate types: 2. equality/null/missing, 5. less than/between/greater than, 9. function index." } ] } } }, "query": "update shellTest set type=\"left\" where length(a21) < 3 and c21 = 3 and c22 > 30</span> |
agora dá
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span style="color: #339966">{ "results": [ { "#operator": "Advise", "advice": { "#operator": "IndexAdvice", "adviseinfo": { "recommended_indexes": { "indexes": [ { "index_statement": "CREATE INDEX adv_c21_length_a21_c22 ON `shellTest`(`c21`,length((`a21`)),`c22`)", "keyspace_alias": "shellTest", "recommending_rule": "Index keys follow order of predicate types: 2. equality/null/missing, 4. not less than/between/not greater than, 5. less than/between/greater than." } ] }</span> <span style="color: #339966">} }, "query": "update shellTest set type=\"left\" where length(a21) <= 3 and c21 = 3 and c22 > 30" } ] } ]</span> |
3. Ajuste a ordem das chaves de índice do array em sua condição SATISFIES
- Coloque os predicados da matriz na ordem da condição SATISFIES.
- Para disjunção em SATISFIES: obtenha os termos comuns -> escolha o de menor prioridade -> (EQ<IN<LE<LT<IS NOT NULL< LIKE)
- Para a conjunção em SATISFIES: escolha o de menor prioridade.
As novas regras após o fix#2 e o #3:
1: índice de matriz principal para unnest,
2: igualdade/nulo/falta,
3: em,
4: não menor que/entre/não maior que,
5: menor que/maior que,
6: filtro de junção derivado como chave principal,
7: não nulo/não ausente/valorizado,
8: como,
9: predicado de união não estático,
10:flavor para índice parcial,
|
1 2 3 4 |
advise SELECT META(p).id, ARRAY_DISTINCT(IFMISSING(rooms[*].num,[])) FROM shellTest AS p WHERE (guestCode = IFNULL($guestCode, '') OR guestCode = '') AND checkinTime BETWEEN $startTime AND $endTime |
usado para dar
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<span style="color: #ff0000">"results": [ { "#operator": "Advise", "advice": { "#operator": "IndexAdvice", "adviseinfo": { "recommended_indexes": { "covering_indexes": [ { "index_statement": "CREATE INDEX adv_guestCode_checkinTime_DISTINCT_rooms_level_size_num_array_di1747996179 ON `shellTest`(`guestCode`,`checkinTime`,DISTINCT ARRAY [`s`.`level`, `s`.`size`, `s`.`num`] FOR s in `rooms` END,array_distinct(ifmissing((array_star((`rooms`)).`num`), [])))", "keyspace_alias": "shellTest_p" } ], "indexes": [ { "index_statement": "CREATE INDEX adv_guestCode_checkinTime_DISTINCT_rooms_level_size_num ON `shellTest`(`guestCode`,`checkinTime`,DISTINCT ARRAY [`s`.`level`, `s`.`size`, `s`.`num`] FOR s in `rooms` END)", "keyspace_alias": "shellTest_p", "recommending_rule": "Index keys follow order of predicate types: 1. Common leading key for disjunction (2. equality/null/missing, 4. not less than/between/not greater than, 6. array predicate)." } ] } } }, "query": "SELECT META(p).id, ARRAY_DISTINCT(IFMISSING(rooms[*].num,[])) FROM shellTest AS p WHERE (guestCode = IFNULL($guestCode, '') OR guestCode = '') AND (checkinTime BETWEEN $startTime AND $endTime) AND (ANY s IN rooms SATISFIES [s.level,s.size, s.num] = [$level, $size, $num] END)" </span> |
agora dá:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span style="color: #339966">results": [ { "#operator": "Advise", "advice": { "#operator": "IndexAdvice", "adviseinfo": { "recommended_indexes": { "covering_indexes": [ { "index_statement": "CREATE INDEX adv_guestCode_checkinTime_array_distinct_ifmissing_array_star_rooms_num ON `shellTest`(`guestCode`,`checkinTime`,array_distinct(ifmissing((array_star((`rooms`)).`num`), [])))", "keyspace_alias": "shellTest_p" } ], "indexes": [ { "index_statement": "CREATE INDEX adv_guestCode_checkinTime ON `shellTest`(`guestCode`,`checkinTime`)", "keyspace_alias": "shellTest_p", "recommending_rule": "Index keys follow order of predicate types: 1. Common leading key for disjunction (2. equality/null/missing, 4. not less than/between/not greater than)." } ] } } }</span> |
Experimente e, se tiver algum problema com os índices recomendados pelo Index Advisor Service, você pode adicioná-lo como um comentário a este blog
Mais informações sobre o recurso Index Advisor:
https://www.couchbase.com/blog/index-advisor-service/
https://www.couchbase.com/blog/index-advisor-service-for-couchbase-n1qlfeb-refresh/
https://www.couchbase.com/blog/n1ql-index-advisor-improve-query-performance-and-productivity/
https://www.couchbase.com/blog/index-advisor-for-query-workload/
https://docs.couchbase.com/server/6.5/n1ql/n1ql-language-reference/advise.html
https://docs.couchbase.com/server/6.5/n1ql/n1ql-language-reference/advisor.html
https://docs.couchbase.com/server/6.5/tools/query-workbench.html#index-advisor