Projects tigase _server server-core Issues #1365
Improve JDBCRepository UserRepository performance when accessing multi-level data (JDBCRepository NID subquery doesn't use index making the call slow) (#1365)
Wojciech Kapcia (Tigase) opened 3 years ago

While tree-like structure of UserData gives quite a lot of flexibility it's not utilised but entails performance issues without much benefit.


mysql> explain select nid as nid2, node as node2 from tig_nodes, (select nid as nid1 from tig_nodes where (uid = 18033992)
AND (parent_nid is null) AND (node = 'root')) nodes1 where (parent_nid = nid1) AND (node = 'message-archive') \G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tig_nodes
   partitions: NULL
         type: ref
possible_keys: PRIMARY,tnode,node,uid,parent_nid
          key: tnode
      key_len: 784
          ref: const,const,const
         rows: 1
     filtered: 100.00
        Extra: Using where; Using index
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: tig_nodes
   partitions: NULL
         type: ref
possible_keys: tnode,node,parent_nid
          key: node
      key_len: 767
          ref: const
         rows: 149706
     filtered: 100.00
        Extra: Using where
2 rows in set, 1 warning (0.00 sec)

Culprit: tigase.db.jdbc.JDBCRepository#buildNodeQuery


The bug is on the SQL query that make the join with the comma.

with a simple subquery all the index works correctly filtering olny 2 rows!

-> https://tigase.dev/C…s/c…l/~issues/31#IssueComment-96568


https://dev.mysql.com/doc/refman/8.0/en/subquery-optimization.html

  • Wojciech Kapcia (Tigase) batch edited 2 years ago
    Name Previous Value Current Value
    Iterations
    empty
    tigase-server-8.4.0
  • Wojciech Kapcia (Tigase) batch edited 2 years ago
    Name Previous Value Current Value
    Iterations
    tigase-server-8.4.0
    tigase-server-8.5.0
    Version
    tigase-server-8.4.0
    tigase-server-8.5.0
  • Wojciech Kapcia (Tigase) changed title 2 years ago
    Previous Value Current Value
    JDBCRepository NID subquery doesn't use index making the call slow
    Flatten UserData (tig_nodes / tig_pairs) schema to avoide performance issues (JDBCRepository NID subquery doesn't use index making the call slow)
  • Wojciech Kapcia (Tigase) added "Related" #1227 2 years ago
  • Wojciech Kapcia (Tigase) added "Related" Customers/catapush-s-r-l#35 2 years ago
  • Wojciech Kapcia (Tigase) batch edited 7 months ago
    Name Previous Value Current Value
    Version
    tigase-server-8.5.0
    8.5.0
  • Wojciech Kapcia (Tigase) added to iteration "tigase-server-9.0.0" 4 days ago
  • Wojciech Kapcia (Tigase) removed from iteration "tigase-server-8.5.0" 4 days ago
  • Wojciech Kapcia (Tigase) changed title 3 days ago
    Previous Value Current Value
    Flatten UserData (tig_nodes / tig_pairs) schema to avoide performance issues (JDBCRepository NID subquery doesn't use index making the call slow)
    Improve JDBCRepository UserRepository performance when accessing multi-level data (JDBCRepository NID subquery doesn't use index making the call slow)
  • Wojciech Kapcia (Tigase) added to iteration "tigase-server-8.5.0" 3 days ago
  • Wojciech Kapcia (Tigase) removed from iteration "tigase-server-9.0.0" 3 days ago
  • Wojciech Kapcia (Tigase) commented 3 days ago

    Changed the implementation to explicitly use INNER JOINS when generating query to get node ID.

    Original query in MySQL where not using indexes most of the time that could result in rather suboptimal performance on bigger repositories:

    mysql> explain select nid as nid6, node as node6
        -> from tig_nodes nodes6,
        ->      (select nid as nid5, node as node5
        ->       from tig_nodes nodes5,
        ->            (select nid as nid4, node as node4
        ->             from tig_nodes nodes4,
        ->                  (select nid as nid3, node as node3
        ->                   from tig_nodes nodes3,
        ->                        (select nid as nid2, node as node2
        ->                         from tig_nodes nodes2,
        ->                              (select nid as nid1
        ->                               from tig_nodes
        ->                               where (uid = 21) AND (parent_nid is null) AND (node = 'root')) nodes1
        ->                         where (parent_nid = nid1)
        ->                           AND (node = 'some')) nodes2
        ->                   where (parent_nid = nid2)
        ->                     AND (node = 'deep')) nodes3
        ->             where (parent_nid = nid3)
        ->               AND (node = 'node')) nodes4
        ->       where (parent_nid = nid4)
        ->         AND (node = 'privacy')) nodes5
        -> where (parent_nid = nid5)
        ->   AND (node = 'blocked');
    +----+-------------+-----------+------------+--------+-----------------------------------+---------+---------+-------------------------------------------+------+----------+--------------------------+
    | id | select_type | table     | partitions | type   | possible_keys                     | key     | key_len | ref                                       | rows | filtered | Extra                    |
    +----+-------------+-----------+------------+--------+-----------------------------------+---------+---------+-------------------------------------------+------+----------+--------------------------+
    |  1 | SIMPLE      | nodes4    | NULL       | ref    | PRIMARY,tnode,node,parent_nid     | node    | 767     | const                                     |    1 |   100.00 | Using where              |
    |  1 | SIMPLE      | nodes3    | NULL       | eq_ref | PRIMARY,tnode,node,parent_nid     | PRIMARY | 8       | tigasedb_inst_qa_b11330.nodes4.parent_nid |    1 |     5.00 | Using where              |
    |  1 | SIMPLE      | nodes2    | NULL       | eq_ref | PRIMARY,tnode,node,parent_nid     | PRIMARY | 8       | tigasedb_inst_qa_b11330.nodes3.parent_nid |    1 |     5.00 | Using where              |
    |  1 | SIMPLE      | tig_nodes | NULL       | eq_ref | PRIMARY,tnode,node,uid,parent_nid | PRIMARY | 8       | tigasedb_inst_qa_b11330.nodes2.parent_nid |    1 |     5.00 | Using where              |
    |  1 | SIMPLE      | nodes5    | NULL       | ref    | PRIMARY,tnode,node,parent_nid     | tnode   | 9       | tigasedb_inst_qa_b11330.nodes4.nid        |    4 |    27.80 | Using where; Using index |
    |  1 | SIMPLE      | nodes6    | NULL       | ref    | tnode,node,parent_nid             | tnode   | 9       | tigasedb_inst_qa_b11330.nodes5.nid        |    4 |    28.06 | Using where; Using index |
    +----+-------------+-----------+------------+--------+-----------------------------------+---------+---------+-------------------------------------------+------+----------+--------------------------+
    

    New with INNER JOIN always uses index:

    mysql> explain SELECT t6.nid
        -> FROM tig_nodes t1
        ->          INNER JOIN tig_nodes t2 ON t2.parent_nid = t1.nid AND t2.uid = 21 AND t2.node = 'some'
        ->          INNER JOIN tig_nodes t3 ON t3.parent_nid = t2.nid AND t3.uid = 21 AND t3.node = 'deep'
        ->          INNER JOIN tig_nodes t4 ON t4.parent_nid = t3.nid AND t4.uid = 21 AND t4.node = 'node'
        ->          INNER JOIN tig_nodes t5 ON t5.parent_nid = t4.nid AND t5.uid = 21 AND t5.node = 'privacy'
        ->          INNER JOIN tig_nodes t6 ON t6.parent_nid = t5.nid AND t6.uid = 21 AND t6.node = 'blocked'
        -> WHERE (t1.uid = 21)
        ->   AND (t1.parent_nid IS NULL)
        ->   AND (t1.node = 'root');
    +----+-------------+-------+------------+--------+-----------------------------------+-------+---------+--------------------------------------------+------+----------+--------------------------+
    | id | select_type | table | partitions | type   | possible_keys                     | key   | key_len | ref                                        | rows | filtered | Extra                    |
    +----+-------------+-------+------------+--------+-----------------------------------+-------+---------+--------------------------------------------+------+----------+--------------------------+
    |  1 | SIMPLE      | t1    | NULL       | ref    | PRIMARY,tnode,node,uid,parent_nid | tnode | 784     | const,const,const                          |    1 |   100.00 | Using where; Using index |
    |  1 | SIMPLE      | t2    | NULL       | eq_ref | PRIMARY,tnode,node,uid,parent_nid | tnode | 784     | tigasedb_inst_qa_b11330.t1.nid,const,const |    1 |   100.00 | Using index              |
    |  1 | SIMPLE      | t3    | NULL       | eq_ref | PRIMARY,tnode,node,uid,parent_nid | tnode | 784     | tigasedb_inst_qa_b11330.t2.nid,const,const |    1 |   100.00 | Using index              |
    |  1 | SIMPLE      | t4    | NULL       | eq_ref | PRIMARY,tnode,node,uid,parent_nid | tnode | 784     | tigasedb_inst_qa_b11330.t3.nid,const,const |    1 |   100.00 | Using index              |
    |  1 | SIMPLE      | t5    | NULL       | eq_ref | PRIMARY,tnode,node,uid,parent_nid | tnode | 784     | tigasedb_inst_qa_b11330.t4.nid,const,const |    1 |   100.00 | Using index              |
    |  1 | SIMPLE      | t6    | NULL       | eq_ref | tnode,node,uid,parent_nid         | tnode | 784     | tigasedb_inst_qa_b11330.t5.nid,const,const |    1 |   100.00 | Using index              |
    +----+-------------+-------+------------+--------+-----------------------------------+-------+---------+--------------------------------------------+------+----------+--------------------------+
    6 rows in set, 1 warning (0.003 sec)
    
  • Wojciech Kapcia (Tigase) changed state to 'Closed' 3 days ago
    Previous Value Current Value
    Open
    Closed
issue 1 of 1
Type
Performance
Priority
Normal
Assignee
Version
8.5.0
Iterations
Issue Votes (0)
Watchers (3)
Reference
tigase/_server/server-core#1365
Please wait...
Page is in error, reload to recover