[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Repeated SQL queries when doing 'svn st'

From: Justin Erenkrantz <justin_at_erenkrantz.com>
Date: Sat, 4 Sep 2010 13:22:18 -0700

On Sat, Sep 4, 2010 at 12:45 PM, Justin Erenkrantz
<justin_at_erenkrantz.com> wrote:
> I'm going to see what a quick check to retrieve just the kind and
> status will do for the query volume.  I think it's unlikely we have to
> pull everything out of sqlite to answer that basic question.  --
> justin

We can reduce the query volume by one (per file) as we can skip the
active table query - see quick & dirty patch below.

It does replace 2 larger queries with 2 smaller ones, but I think our
bottleneck is likely more around query volume than query complexity...

Anyway, I'll stop replying to myself and enjoy the long weekend. =) -- justin

Index: status.c
===================================================================
--- status.c (revision 992534)
+++ status.c (working copy)
@@ -1263,10 +1270,7 @@ get_dir_status(const struct walk_status_baton *wb,
           svn_wc__db_status_t node_status;
           svn_wc__db_kind_t node_kind;

- SVN_ERR(svn_wc__db_read_info(&node_status, &node_kind, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
+ SVN_ERR(svn_wc__db_read_info_exist(&node_status, &node_kind,
                                    wb->db, node_abspath, iterpool, iterpool));

           if (node_status != svn_wc__db_status_not_present
Index: wc_db.c
===================================================================
--- wc_db.c (revision 992534)
+++ wc_db.c (working copy)
@@ -51,7 +51,6 @@
 #include "private/svn_wc_private.h"
 #include "private/svn_token.h"

-
 #define NOT_IMPLEMENTED() SVN__NOT_IMPLEMENTED()

@@ -5051,6 +5050,161 @@ svn_wc__db_temp_op_delete(svn_wc__db_t *db,

 svn_error_t *
+svn_wc__db_read_info_exist(svn_wc__db_status_t *status,
+ svn_wc__db_kind_t *kind,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+ svn_sqlite__stmt_t *stmt_base;
+ svn_sqlite__stmt_t *stmt_work;
+ svn_boolean_t have_base;
+ svn_boolean_t have_work;
+ svn_error_t *err = NULL;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ local_abspath, svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt_base, pdh->wcroot->sdb,
+ STMT_SELECT_BASE_NODE_EXIST));
+ SVN_ERR(svn_sqlite__bindf(stmt_base, "is",
+ pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_base, stmt_base));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt_work, pdh->wcroot->sdb,
+ STMT_SELECT_WORKING_NODE_EXIST));
+ SVN_ERR(svn_sqlite__bindf(stmt_work, "is",
+ pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_work, stmt_work));
+
+ if (have_base || have_work)
+ {
+ svn_wc__db_kind_t node_kind;
+
+ if (have_work)
+ node_kind = svn_sqlite__column_token(stmt_work, 1, kind_map);
+ else
+ node_kind = svn_sqlite__column_token(stmt_base, 1, kind_map);
+
+ if (status)
+ {
+ if (have_base)
+ {
+ *status = svn_sqlite__column_token(stmt_base, 0, presence_map);
+
+ /* We have a presence that allows a WORKING_NODE override
+ (normal or not-present), or we don't have an override. */
+ /* ### for now, allow an override of an incomplete BASE_NODE
+ ### row. it appears possible to get rows in BASE/WORKING
+ ### both set to 'incomplete'. */
+ SVN_ERR_ASSERT((*status != svn_wc__db_status_absent
+ && *status != svn_wc__db_status_excluded
+ /* && *status != svn_wc__db_status_incomplete */)
+ || !have_work);
+
+#ifndef SVN_WC__SINGLE_DB
+ if (node_kind == svn_wc__db_kind_subdir
+ && *status == svn_wc__db_status_normal)
+ {
+ /* We should have read a row from the subdir wc.db. It
+ must be obstructed in some way.
+
+ It is also possible that a WORKING node will override
+ this value with a proper status. */
+ *status = svn_wc__db_status_obstructed;
+ }
+#endif
+ }
+
+ if (have_work)
+ {
+ svn_wc__db_status_t work_status;
+
+ work_status = svn_sqlite__column_token(stmt_work, 0,
+ presence_map);
+ SVN_ERR_ASSERT(work_status == svn_wc__db_status_normal
+ || work_status == svn_wc__db_status_not_present
+ || work_status == svn_wc__db_status_base_deleted
+ || work_status == svn_wc__db_status_incomplete
+ || work_status == svn_wc__db_status_excluded);
+
+ if (work_status == svn_wc__db_status_incomplete)
+ {
+ *status = svn_wc__db_status_incomplete;
+ }
+ else if (work_status == svn_wc__db_status_excluded)
+ {
+ *status = svn_wc__db_status_excluded;
+ }
+ else if (work_status == svn_wc__db_status_not_present
+ || work_status == svn_wc__db_status_base_deleted)
+ {
+ /* The caller should scan upwards to detect whether this
+ deletion has occurred because this node has been moved
+ away, or it is a regular deletion. Also note that the
+ deletion could be of the BASE tree, or a child of
+ something that has been copied/moved here. */
+
+#ifndef SVN_WC__SINGLE_DB
+ /* If we're looking at the data in the parent, then
+ something has obstructed the child data. Inform
+ the caller. */
+ if (node_kind == svn_wc__db_kind_subdir)
+ *status = svn_wc__db_status_obstructed_delete;
+ else
+#endif
+ *status = svn_wc__db_status_deleted;
+ }
+ else /* normal */
+ {
+ /* The caller should scan upwards to detect whether this
+ addition has occurred because of a simple addition,
+ a copy, or is the destination of a move. */
+
+#ifndef SVN_WC__SINGLE_DB
+ /* If we're looking at the data in the parent, then
+ something has obstructed the child data. Inform
+ the caller. */
+ if (node_kind == svn_wc__db_kind_subdir)
+ *status = svn_wc__db_status_obstructed_add;
+ else
+#endif
+ *status = svn_wc__db_status_added;
+ }
+ }
+ }
+ if (kind)
+ {
+#ifndef SVN_WC__SINGLE_DB
+ if (node_kind == svn_wc__db_kind_subdir)
+ *kind = svn_wc__db_kind_dir;
+ else
+#endif
+ *kind = node_kind;
+ }
+ }
+ else
+ {
+ err = svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+ }
+
+ err = svn_error_compose_create(err, svn_sqlite__reset(stmt_base));
+ SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt_work)));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_wc__db_read_info(svn_wc__db_status_t *status,
                      svn_wc__db_kind_t *kind,
                      svn_revnum_t *revision,
Index: wc_db.h
===================================================================
--- wc_db.h (revision 992534)
+++ wc_db.h (working copy)
@@ -1523,7 +1523,16 @@ svn_wc__db_read_info(svn_wc__db_status_t *status,
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool);

+svn_error_t *
+svn_wc__db_read_info_exist(svn_wc__db_status_t *status, /* ### derived */
+ svn_wc__db_kind_t *kind,

+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
 /* Set *PROPVAL to the value of the property named PROPNAME of the node
    LOCAL_ABSPATH in the ACTUAL tree (looking through to the WORKING or BASE
    tree as required).
Index: wc-queries.sql
===================================================================
--- wc-queries.sql (revision 992534)
+++ wc-queries.sql (working copy)
@@ -43,6 +43,11 @@ left outer join lock on base_node.repos_id = lock.
   and base_node.repos_relpath = lock.repos_relpath
 where wc_id = ?1 and local_relpath = ?2;

+-- STMT_SELECT_BASE_NODE_EXIST
+select presence, kind
+from base_node
+where wc_id = ?1 and local_relpath = ?2;
+
 -- STMT_SELECT_WORKING_NODE
 select presence, kind, checksum, translated_size,
   changed_rev, changed_date, changed_author, depth, symlink_target,
@@ -51,6 +56,11 @@ select presence, kind, checksum, translated_size,
 from working_node
 where wc_id = ?1 and local_relpath = ?2;

+-- STMT_SELECT_WORKING_NODE_EXIST
+select presence, kind
+from working_node
+where wc_id = ?1 and local_relpath = ?2;
+
 -- STMT_SELECT_ACTUAL_NODE
 select prop_reject, changelist, conflict_old, conflict_new,
 conflict_working, tree_conflict_data, properties
Received on 2010-09-04 22:23:13 CEST

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.