MySQL views performance with select * from tablename definition - mysql

I have created views with following generic definition on all of my tables required for reporting
select * from tablename
Ideally views with this definition should use merge algorithm.
Can someone please tell me if the performance of these views with the above definition will be comparable to the physical tables?

Check out this link.
By above report, derived table shows poor performance than table, while simple view works good. But if you run a query with ORDER or WHERE on view, it will be slower than naive table. (see comments on the link )
And use EXPLAIN to checkout your queries between view and table.

Related

CREATE OR REPLACE VIEW Vs Checking view existing or not?

I am using Maria DB 5.5 version and it does not allow clause ‘CREATE VIEW IF NOT EXISTS’ while view creation. As requirement, I need to check whether view existing or not while creation.
Here I have 2 approach for this problem …
Do SQL using INFORMATION_SCHEMA.TABLES and create the view only if view is not present
Use ‘CREATE OR REPLACE VIEW’ so that no error/warning should throw if view is already present if view might have to handle more than 50k records.
Out of these 2 options, which options is better & recommended approach?
If you must know whether the view existed before your operation, using the information schema is helpful.
Otherwise, CREATE OR REPLACE is much simpler. Your view definition can stand alone as a DDL statement.
The first option requires the server to process several queries, so it will take slightly longer than the second option. But view creation (in MySQL and MariaDB) is very fast: no actual data is retrieved until you use the view in a query.
So the VIEW contains an ever-growing UNION across many databases. So, the only way the VIEW would not exist is when two new users are updating the view 'simultaneously'.
Suggested workaround:
SELECT GET_LOCK('update_view');
DROP VIEW ...;
CREATE VIEW ...;
SELECT RELEASE_LOCK('update_view');
This avoids the need for OR REPLACE (etc), except for the very first time -- when the DROP VIEW will complain that the VIEW does not exist. That can be solved by creating a dummy VIEW when the machine is first configured.
(Study the parameters on GET_LOCK.)

Access query runs on table that does not exist in database

I would like to recreate a few existing Access queries in a new database so that I can tweak them a bit. The problem I am running into is that some of the tables being queried do not seem to exist in the current database. These tables all end with a 1.
For example, INV_MTL_ITEM_LOCATIONS is an imported table in the database, but
INV_MTL_ITEM_LOCATIONS_1 is being queried even though it does not show up in the tables panel on the left.
Is this some type of duplication functionality that I am not aware of? The query runs without any errors.
No, the query runs on an aliased table. It's actually just querying INV_MTL_ITEM_LOCATIONS
Using SQL, you can create an alias for a table. This is especially useful when querying the same table twice in one query, but also commonly used to shorten queries.
Your query will probably look something like this:
SELECT something
FROM INV_MTL_ITEM_LOCATIONS AS INV_MTL_ITEM_LOCATIONS_1
Access automatically creates these aliases when using the query builder and if you add the same table more than once. When removing the non-aliased table, the other one stays aliased.
This is entirely normal, and as far as I know, never a problem.
Erik's answer explains it perfectly.
But to be exhaustive, you CAN actually create a query on a table that is NOT in the current database (nor a linked table).
Here is an example:
SELECT *
FROM History IN 'c:\test\mySecretBackend.accdb'
You can also create that in design view, just by
setting the query's Source Database property to c:\test\mySecretBackend.accdb
click on Show table

Materialized view in mysql

How to create a materialized view in mysql ?
I am not able to create a materialized view as we do in MS SQL Server.
Could anyone let me know the ways to create it in mysql.
Here's what I've had success with so far:
Using triggers - you can set triggers on the source tables on which you build the view. This minimizes the resource usage as the refresh is only done when needed. Also, data in the materialized view is realtime-ish
Using cron jobs with stored procedures or SQL scripts - refresh is done on a regular basis. You have more control as to when resources are used. Obviously you data is only as fresh as the refresh-rate allows.
Using MySQL scheduled events - similar to 2, but runs inside the database
Flexviews - using FlexDC mentioned by Justin. The closest thing to real materialized views
I've been collecting and analyzing these methods, their pros and cons in my article Creating MySQL materialized views
looking forwards for feedback or proposals for other methods for creating materialized views in MySQL
You can create a non-updateable dynamic view - and if you've got (indexed) timestamps in the underlying table(s) you can add in a snapshot, something like:
CREATE VIEW almost_materialzd
AS
SELECT snp.*
FROM snapshot snp
WHERE s.id NOT IN (SELECT id
FROM source_data sd
INNER JOIN ref_data rd
ON rd.value='snapshot of source_data'
AND sd.update_timestamp>rd.timetamp)
UNION
SELECT *
FROM source_data sd2
INNER JOIN ref_data rd2
ON rd2.value='snapshot of source_data'
AND sd2.update_timestamp>rd2.timetamp);
But a better solution is to add a trigger (or triggers) to the the underlying table(s) to re-populate the relevant rows in a table representing the materialized view when the underlying tables are changed.
www.LeapDB.com provides MySQL materialized views. straight forward with the proper syntax. It's an add on to MySQL.

What is the best way to filter a multi-tenant MySQL database?

In MySQL I have a single database with one schema. In Microsoft Sql Server it is recommended to use a "Tenant View Filter" so in Microsoft Sql Server this gives me exactly what I need.
CREATE VIEW TenantEmployees AS
SELECT * FROM Employees WHERE TenantID = SUSER_SID()
What is the best way to accomplish the same in MySQL? An equivalent to the "Tenant View Filter" will work if it is performs well.
Thanks!!
The query you suggest (that I could find in MSDN) has text afterwards that explains exactly what are its assumptions. In particular, it mentions that it assumes that the "owner" of a row in the Employees table is specified in the TenantID field that is populated according to the SID of the user(s) you are partitioning for.
What that means is that you can replicate the same idea whatever way you decide to implement your data as long as you have clearly defined partitions of the data and know exactly how to associate it with the table you are creating a view for.
In particular, if you configure your system so that each partition accesses the DB with its own credentials, you could use the CURRENT_USER or USER constructs of MySQL as the IDs defining your partitions and the query to create the view would be basically the same as the one suggested in MSDN replacing SUSER_ID with CURRENT_USER.
But if you use the same user to access from all the partitions, then the suggested method is irrelevant on either database server.
Since you need to use your tenantId value to perform filtering, a table valued user defined function would be ideal, as a view normally does not accept parameters. Unfortunately, unlike many other database products MySQL doesn't support table-valued functions. However, there are MySQL hacks that claim to emulate parametrized views. These could be useful for you.
It's a little tricky in MySQL, but it can be done:
CREATE OR REPLACE VIEW {viewName}
AS
SELECT {fieldListWithoutTenantID}
FROM {tableName}
WHERE (id_tenant = SUBSTRING_INDEX(USER( ),'#',1))
I wrote up a full blog post on how I converted a single-tenant MySQL application to multi-tenant in one weekend with minimal changes. https://opensource.io/it/mysql-multi-tenant/

Saving commands for later re-use in MySQL?

What would be the equivalant in MySQL for:
Saving a command for later reuse.
eg: alias command1='select count(*) from sometable;'
Where then I simply type command 1 to get the count for SomeTable.
Saving just a string, or rather part of a command.
eg: select * from sometable where $complex_where_logic$ order by attr1 desc;
WHere $complex_where_logic$ is something I wish to save and not have to keep writing out
Another approach is to create a view with your $complex_where_logic$ and query the view instead of the tables:
CREATE VIEW my_view AS SELECT * FROM sometable WHERE $complex_where_logic$
SELECT my_column FROM my_view ORDER BY some_column
Whenever you query a view, you always get the up-to-date data. Internally, MySQL runs the SELECT given in the CREATE VIEW statement and queries the results in order to obtain the results of your current SELECT. Therefore, a view does not improve performance compared to a single query. There a two main advantages in using views:
you have simpler SELECT statements since you do not have to type complex WHERE or JOIN Syntax again and again
you can use it to control user privileges, e.g. give a user access to a view but not to the original tables; this is not useful in your example, but - for example - you can think of views containing aggregate data only
This "template" feature could be part of client tools. Basically I use Toad. It has record macros feature. I think it is possible to do.
I take it the answer you are looking for isn't 'stored procedures'...?
I found that the best solution for this is just any rich GUI for SQL queries (TOAD, mysql query browser, etc). They offer the ability to save commands and browse them and well, of course, much more.