I use databases all of the time within various solutions, but never really design them. Therefore, I’m pretty new to the finer points of SQL. I have a database that has many tables, but 2 main ones:
Item – references lots of other tables for data that doesn’t change with revisions and
Entry – references lots of other tables for data that does change with revisions
Each item will therefore have 1 or more revision (with all associated data).
I want to select all data for all revisions (and consequently items) with a view. I’ve structured a single query as follows:
CREATE VIEW Single_Query
AS
SELECT i.REF_CODE AS REF
gp.GROUP_NAME AS Group
v.VERSION_NUMBER AS Version
GROUP_CONCAT(DISTINCT(cy.COUNTRY_DESCRIPTION) SEPARATOR ', ') AS Country
ey.PUB_DATE AS Published
GROUP_CONCAT(DISTINCT(ct.CONTRIBUTOR_NAME) SEPARATOR ', ') AS Author
i.ISBN_CODE AS ISBN
GROUP_CONCAT(DISTINCT CONCAT(cn.COMPONENT_NUMBER, _utf8', ',cn.COMPONENT_DESCRIPTION) SEPARATOR '; ') AS Contents
ey.NOTES AS Notes
i.PRICE AS Price
cl.COLOUR_DESCRIPTION AS Colour
FROM entry AS ey
JOIN item AS i ON ey.ITEM_ID = i.ITEM_ID
JOIN group AS gp ON i.GROUP_ID = gp.GROUP_ID
JOIN version AS v ON ey.VERSION_ID = v.VERSION_ID
JOIN link_country_item AS lci ON i.ITEM_ID = lci.ITEM_ID
JOIN country AS cy ON lci.COUNTRY_ID = cy.COUNTRY_ID
LEFT JOIN link_entry_contributor AS lec ON ey.ENTRY_ID = lec.ENTRY_ID
LEFT JOIN contributor AS ct ON lec.CONTRIBUTOR_ID = ct.CONTRIBUTOR_ID
JOIN contents AS cn ON i.ITEM_ID = cn.ITEM_ID
JOIN colour AS cl ON ey.COLOUR_ID = cl.COLOUR_ID
GROUP BY REF_CODE, VERSION_NUMBER
This takes about 29 seconds to complete, with only a few entries! However, if I run a script to create temporary tables for the item data (and all referenced data) and the entry data (and all referenced data), then select the whole lot from the 2 temporary tables with a single JOIN on ITEM_ID, then it takes less than half a second to complete.
Note that there are lots of other referenced tables (I’ve omitted them for clarity).
If it helps, the item table references the group, setting (through the many-many link_country_item table) and contents tables.
The entry table references the version, contributor (through the many-many link_entry_contributor table) and colour tables.
The problem is that I don’t really want to use temporary tables all of the time as I can’t use them in a view (or at least I haven’t found out how). Is there a more elegant way of splitting the SQL in a View so that it runs faster in this scenario?
Many Thanks in advance
Iain
I’ve slightly restructured the querying order, and see your comment about the REF_CODE. So you are correct, the original index answer wouldn’t cover for you. However, with the item table in the primary position, if that has an index on (REF_CODE, ITEM_ID) should help the performance, as you are STARTING with the table, and a corresponding index for your GROUP BY clause.