Does a union ruin indexing in MySQL 5.6? - mysql

A question on how MySQL works under the hood. Say I have two tables, table1, and table2_archive. They are identical in columns and indexed columns.
If I try running queries that involve
(
SELECT * FROM table1
UNION
SELECT * FROM table1
) as allTable1
in the middle of it, with where and join clauses on columns of the newly formed allTable1, are the indexes previously declared on table1/table1_archive now not helpful give they were turned into a new table?
Same qusetion for something like
SELECT IF table1.col1 IS NULL THEN table1_archive.col1 ELSE table1.col1.
I am using MySQL 5.6.

Related

Optimizing a view including a union in Mysql before version 8.0

I have a view that combines the contents of two tables like this
CREATE VIEW my_view AS
(SELECT some_key, x FROM a)
UNION ALL
(SELECT some_key, x FROM b)
I want to query the view like this:
SELECT * FROM my_view WHERE some_key = '123'
This is possible but it's very slow since the complete view seems to be materialized before applying the filter/condition. In theory the condition can be pushed down to both the selects the union is made of but it's not happening. It appears this feature is available in MySQL 8.0
How can I work around this in earlier versions of MySQL? I thought about left joining both tables to another table with the same key to trick MySQL into applying the where condition first but I didn't succeed. I assume it would even be faster when I would run over the matching keys and generate the union separately only for the matching records in both tables. I thought about doing this with a kind of subquery within a select on the third table (containing only the keys) but i don't know how I could union the results again.

MySql select all from two tables result in a lot of duplicates

I'm using mysql db from oracle (latest version 8.*).
I'm using node js with express. I have several tables with the exact same layout.
All using an auto_increment id and some columns.
For the index page. I need the fetch all data from multiple tables.
I have the following tables: beers (100 rows), non_alcoholic_beers(7 rows) and red_wines(50 rows).
Accordingly to the Oracle documentation a simple:
SELECT * FROM table1, table2; or
SELECT * FROM table1 join table2;
should suffice.
It's works kinda....
But if I do this I get 52+K records. A lot of duplicates thus. I only expect 157 records.
A simple: 'SELECT * FROM table1;' works perfectly.
Can anyone show some light on this matter?
Thanks in advance
If your tables are not related to each other (no foreign key) and you just want to get all the results combined you should use UNION.
It merges the result of queries . You can try it like
Select * from table1
UNION
Select * from table2

Better way to get 15 tables results at a time in MySql

I have about 20 tables. These tables have only id (primary key) and description (varchar). The data is a lot reaching about 400 rows for one table.
Right now I have to get data of at least 15 tables at a time.
Right now I am calling them one by one. Which means that in one session I am giving 15 calls. This is making my process slow.
Can any one suggest any better way to get the results from the database?
I am using MySQL database and using Java Springs on server side. Will making view for all combined help me ?
The application is becoming slow because of this issue and I need a solution that will make my process faster.
It sounds like your schema isn't so great. 20 tables of id/varchar sounds like a broken EAV, which is generally considered broken to begin with. Just the same, I think a UNION query will help out. This would be the "View" to create in the database so you can just SELECT * FROM thisviewyoumade and let it worry about the hitting all the tables.
A UNION query works by having multiple SELECT stataements "Stacked" on top of one another. It's important that each SELECT statement has the same number, ordinal, and types of fields so when it stacks the results, everything matches up.
In your case, it makes sense to manufacturer an extra field so you know which table it came from. Something like the following:
SELECT 'table1' as tablename, id, col2 FROM table1
UNION ALL
SELECT 'table2', id, col2 FROM table2
UNION ALL
SELECT 'table3', id, col2 FROM table3
... and on and on
The names or aliases of the fields in the first SELECT statement are the field names that are used in the result set that is returned, so no worries about doing a bunch AS blahblahblah in subsequent SELECT statements.
The real question is whether this union query will perform faster than 15 individual calls on such a tiny tiny tiny amount of data. I think the better option would be to change your schema so this stuff is already stored in one table just like this UNION query outputs. Then you would need a single select statement against a single table. And 400x20=8000 is still a dinky little table to query.
To get a row of all descriptions into app code in a single roundtrip send a query kind of
select t1.description, ... t15.description
from t -- this should contain all needed ids
join table1 t1 on t1.id = t.t1id
...
join table1 t15 on t15.id = t.t15id
I cannot get you what you really need but here merging all those table values into single table
CREATE TABLE table_name AS (
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t1.ID=t2.ID AND
...
LEFT JOIN tableN tN ON tN-1.ID=tN.ID
)

Multiple table counts in one query

I've done some searching around but I haven't found a clear answer and explanation to my question.
I have 5 tables called table1, table2, table3, table4 and table5 and I want to do COUNT(*) on each of the tables to get the number of rows.
Should I try to combine these into one query or use 5 separate queries? I have always been taught that the least number of queries the better so I am guessing I should try to combine them into one query.
One way of doing it is to use UNION but does anyone know what the most efficient way of doing this is and why?
Thanks for any help.
Assuming you just want a count(*) from each one, then
SELECT
( SELECT count(*) from table1 ) AS table1,
( SELECT count(*) from table2 ) AS table2,
( SELECT count(*) from table3 ) AS table3,
etc...
)
would give you those counts as a single row. The DB server would still be running n+1 queries (n tables, 1 parent query) to get those counts, but it'd be the same story if you were using a UNION anyways. The union would produce multiple rows with 1 value in each, v.s. the 1 row with multiple values of the subselect method.
Provided you have read access to this (so rather not on shared hosting where you don’t have your actual own database instance) you could read that info from the INFORMATION_SCHEMA TABLES table, that does have a TABLE_ROWS column.
(Be aware of what it says for InnoDB tables there – so if you don’t you MyISAM and need the precise counts, the other answer has the better solution.)

multi row "dual" table in mysql/sql

This is an extension of the "dual" table concept (temporary table created on the fly for one query and discarded straight after)
I am trying to join a multi row dual table with another one, so as to avoid to have to run the same query several times with different parameters, using 1 statement.
One of the issue I am having is that union is very slow for dual tables, and I am unaware of any more efficient way to accomplish the following. (100 ms when joining 50 dual together)
SELECT
b.id,
b.ref_unid,
a.date
FROM
(
SELECT
'b8518a84-c501-11dd-b0b6-001d7dc91168' as unid,
'2010-01-05' as date
UNION
SELECT
'b853a1f2-c501-11dd-b0b6-001d7dc91168',
'2010-01-06'
UNION
SELECT
'b8557bd0-c501-11dd-b0b6-001d7dc91168',
'2010-01-07'
/* ... */
) as a
join other_table b
ON
b.ref_unid = a.unid
Is there another way of accomplishing this goal?
Is there any syntax similar to that of insert into values statement that would accomplish that goal, such as:
SELECT
unid,
id
FROM
(
WITH (unid, date) USING VALUES
(
('b8518a84-c501-11dd-b0b6-001d7dc91168','2010-01-05'),
('b853a1f2-c501-11dd-b0b6-001d7dc91168','2010-01-06'),
('b8557bd0-c501-11dd-b0b6-001d7dc91168','2010-01-07'),
/* ... */
)
) as a
join other_table b
ON
b.ref_unid = a.unid
I'm looking for a 1-statement solution. Multiple trips to the database aren't possible.
There's no other convention I'm aware of that's available in MySQL to construct a derived table in a single statement. If this dealt with a single column, at ~50 values it could be converted to use an IN clause.
The best performing approach is to load the data into a table of one form or another -- in MySQL, for a temporary use I'd recommend using the MEMORY engine. At ~50 tuples, I have to wonder why the data isn't already in the database...