Blocker for #412518: Convert taxonomy_node_* related code to use field API + upgrade path.

Problems in field_sql_storage.module:
- all 'meta' columns (id, vid, bundle...) can potentially be used as conditions in f_a_query(), so they should all be indexed.
- field_sql_storage choses to store 'entity types' as numeric ids, using a separate mapping table (see #361843: Convert entity type columns from varchar to int)
The JOIN on {field_config_entity_type} in field_sql_storage_field_storage_query() causes a filesort if there's a condition on 'entity type'.

Attach patch should fix this - note that I'm not sure why need the existing 'primary key' at all on field data tables..

Comments

yched’s picture

StatusFileSize
new3.2 KB

Wrong copy/paste, previous patch added the index on 'entity_id' twice.

yched’s picture

StatusFileSize
new2.81 KB

Sorry, try again.

catch’s picture

yched beat me to it opening the issue, subscribing.

yched’s picture

StatusFileSize
new2.81 KB

Found another bug, so I figured it was time to run the tests before posting a patch :-p.
This one passes field_attach_query tests.

yched’s picture

StatusFileSize
new2.42 KB

Removes crufty code.
Trying to provide quick patches late at night only makes me look like an *ss and flood poor test bot. We should be there now :-p.

catch’s picture

Before:

mysql> EXPLAIN SELECT t.bundle AS bundle, t.entity_id AS entity_id, t.revision_id AS revision_id, e.type AS type FROM field_data_taxonomy_tags_2 t INNER JOIN field_config_entity_type e ON t.etid = e.etid WHERE (taxonomy_tags_value = 1) AND (type = 'node') AND (deleted = 0) ORDER BY t.etid ASC, t.entity_id ASC;
+----+-------------+-------+-------+-----------------------------+---------+---------+-------+-------+-----------------------------+
| id | select_type | table | type  | possible_keys               | key     | key_len | ref   | rows  | Extra                       |
+----+-------------+-------+-------+-----------------------------+---------+---------+-------+-------+-----------------------------+
|  1 | SIMPLE      | e     | const | PRIMARY,type                | type    | 767     | const |     1 | Using index; Using filesort |
|  1 | SIMPLE      | t     | ref   | PRIMARY,taxonomy_tags_value | PRIMARY | 4       | const | 17683 | Using where                 |
+----+-------------+-------+-------+-----------------------------+---------+---------+-------+-------+-----------------------------+
2 rows in set (0.03 sec)

After:

mysql> EXPLAIN SELECT t.bundle AS bundle, t.entity_id AS entity_id, t.revision_id AS revision_id, e.type AS type FROM field_data_taxonomy_mila_4 t INNER JOIN field_config_entity_type e ON t.etid = e.etid WHERE (taxonomy_mila_value = 1) AND (t.etid = 2) AND (deleted = 0) ORDER BY t.etid ASC, t.entity_id ASC;
+----+-------------+-------+-------+------------------------------------------+---------+---------+-------+------+-------------+
| id | select_type | table | type  | possible_keys                            | key     | key_len | ref   | rows | Extra       |
+----+-------------+-------+-------+------------------------------------------+---------+---------+-------+------+-------------+
|  1 | SIMPLE      | e     | const | PRIMARY                                  | PRIMARY | 4       | const |    1 |             | 
|  1 | SIMPLE      | t     | ref   | PRIMARY,etid,deleted,taxonomy_mila_value | PRIMARY | 4       | const | 7424 | Using where | 
+----+-------------+-------+-------+------------------------------------------+---------+---------+-------+------+-------------+
2 rows in set (0.00 sec)

Better, still not using an index though.

yched’s picture

Strange, all columns used in the WHERE should be indexed now. Can you check the actual data table and see what are the indexes there ?
+ (sorry to add) Just applying the patch won't add the indexes on the table for an existing field, obviously. Testing an existing benchmark setup would require creating the indexes manually.

Or is MySQL chosing to use the primary key (which again, I'm not sure we need anymore) instead of the individual indexes that would be more efficient ?

catch’s picture

I did a re-install of field_sql_storage.module, then upgraded my taxonomy data with the latest patch from that issue - so all the indexes should be there afaik, although I'll double check.

It's possible we need a composite index covering both the where and order by, although if the primary key covers that I dunno.

mysql> SHOW INDEXES FROM field_data_taxonomy_mila_4;
+----------------------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table                      | Non_unique | Key_name            | Seq_in_index | Column_name         | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------------------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
| field_data_taxonomy_mila_4 |          0 | PRIMARY             |            1 | etid                | A         |           3 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          0 | PRIMARY             |            2 | entity_id           | A         |       27624 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          0 | PRIMARY             |            3 | deleted             | A         |       27624 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          0 | PRIMARY             |            4 | delta               | A         |       27624 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          0 | PRIMARY             |            5 | language            | A         |       27624 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          1 | etid                |            1 | etid                | A         |           1 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          1 | bundle              |            1 | bundle              | A         |           1 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          1 | deleted             |            1 | deleted             | A         |           1 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          1 | entity_id           |            1 | entity_id           | A         |       27624 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          1 | revision_id         |            1 | revision_id         | A         |       27624 |     NULL | NULL   | YES  | BTREE      |         | 
| field_data_taxonomy_mila_4 |          1 | language            |            1 | language            | A         |           1 |     NULL | NULL   |      | BTREE      |         | 
| field_data_taxonomy_mila_4 |          1 | taxonomy_mila_value |            1 | taxonomy_mila_value | A         |        6906 |     NULL | NULL   | YES  | BTREE      |         | 
+----------------------------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
12 rows in set (0.02 sec)

I thought it might be the join, but I get where in extra without that too.

yched’s picture

I did not try with the taxo_node_* patch, but the equivalent query on field 'body' shows no extra (querying on 'format' column, which is indexed)

mysql> EXPLAIN SELECT t.bundle AS bundle, t.entity_id AS entity_id, t.revision_id AS revision_id, e.type AS type FROM field_data_body_1 t INNER JOIN field_config_entity_type e ON t.etid = e.etid WHERE (body_format = 1) AND (type = 'node') AND (deleted = 0) ORDER BY t.etid ASC, t.entity_id ASC;
+----+-------------+-------+--------+----------------------------------+---------+---------+-------+------+-------+
| id | select_type | table | type   | possible_keys                    | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+--------+----------------------------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | t     | system | PRIMARY,body_format,etid,deleted | NULL    | NULL    | NULL  |    1 |       |
|  1 | SIMPLE      | e     | const  | PRIMARY,type                     | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+--------+----------------------------------+---------+---------+-------+------+-------+
2 rows in set (0.00 sec)
mysql> SHOW INDEXES FROM field_data_body_1;
+-------------------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table             | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| field_data_body_1 |          0 | PRIMARY     |            1 | etid        | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          0 | PRIMARY     |            2 | entity_id   | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          0 | PRIMARY     |            3 | deleted     | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          0 | PRIMARY     |            4 | delta       | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          0 | PRIMARY     |            5 | language    | A         |           1 |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          1 | body_format |            1 | body_format | A         |        NULL |     NULL | NULL   | YES  | BTREE      |         |
| field_data_body_1 |          1 | etid        |            1 | etid        | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          1 | bundle      |            1 | bundle      | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          1 | deleted     |            1 | deleted     | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          1 | entity_id   |            1 | entity_id   | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| field_data_body_1 |          1 | revision_id |            1 | revision_id | A         |        NULL |     NULL | NULL   | YES  | BTREE      |         |
| field_data_body_1 |          1 | language    |            1 | language    | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
+-------------------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
12 rows in set (0.00 sec)
catch’s picture

@yched - from the show indexes, it looks like there's no cardinality in the table you're running the explain on. Could you try with some dummy content and confirm if it's the same?

yched’s picture

Sorry, I had only one record in the table :-p. With 2 records, 'using where' shows up.
But it seems it shows up whenever there are more than 2 columns in the WHERE clause and no index for all those columns as a whole, so I'm not sure we can do better.

yched’s picture

PS: and the query in my #9 should read

EXPLAIN SELECT t.bundle AS bundle, t.entity_id AS entity_id, t.revision_id AS revision_id, e.type AS type FROM field_data_body_1 t INNER JOIN field_config_entity_type e ON t.etid = e.etid WHERE (body_format = 1) AND (t.etid = 3) AND (deleted = 0) ORDER BY t.etid ASC, t.entity_id ASC;

(new query after the patch)

catch’s picture

Status: Needs review » Reviewed & tested by the community

OK let's do this and look at multiple-column index support either as a follow-up in this issue or a new one, it's already an improvement.

catch’s picture

Issue tags: +API change

Schema changes are apparently API changes - while this would have to go in post-freeze anyway, it'll also help some other patches out.

dries’s picture

+++ modules/field/modules/field_sql_storage/field_sql_storage.module	29 Aug 2009 01:09:51 -0000
@@ -461,6 +469,20 @@
+    // Translate entity types into numeric ids, to avoid adding conditions on
+    // the external field_config_entity_type table.

I wonder if we could be a little bit more verbose here.

This review is powered by Dreditor.

yched’s picture

StatusFileSize
new2.46 KB

Sure, what about this ?

dries’s picture

Status: Reviewed & tested by the community » Fixed

Committed to CVS HEAD. Thanks.

Status: Fixed » Closed (fixed)
Issue tags: -API change

Automatically closed -- issue fixed for 2 weeks with no activity.