DeLe
DeLe

Reputation: 2480

Php, Mysql - How to working with big data in my case

I have two table with big data, Example in http://www.sqlfiddle.com/#!2/ee61b/3

Table 1 like

CREATE TABLE `t1`(
  `id` int(4) ,
  `name` varchar(40),
  `signal` int(4)
)
;

INSERT INTO `t1`
(`id`, `name`, `signal`)
VALUES
    (1, 'a', 1),
    (2, 'b', 1),
    (3, 'c', 0),
    (4, 'd', 0)
;

And table 2 like

CREATE TABLE `t2`(
  `uid` int(4),
  `type` int(4),
  `usignal` int(4)
)
;

INSERT INTO `t2`
(`uid`, `type`, `usignal`)
VALUES
    (3, 1, 1),
    (1, 2, 1),
    (4, 1, 0),
    (2, 2, 0)
;

Now i try to get all record have conditional like
1. All record in table 1 has signal = 1
2. OR(+) all record in table 1 has id in (SELECT uid FROM t2 WHERE t2.type = 1 AND t2.usignal = 1)

I do that like

SELECT * FROM `t1` AS g1
WHERE g1.signal = 1
UNION 
SELECT * FROM  `t1` AS g1
WHERE g1.id
IN (
    SELECT uid
    FROM  `t2` AS g2
    WHERE g2.usignal = 1 AND g2.type = 1
)

But I must do some conditional on that (mybe join,...) and i do that like

SELECT * FROM `t1` AS g1
WHERE g1.signal = 1
UNION 
SELECT * FROM  `t1` AS g1
WHERE g1.id
IN (
    SELECT uid
    FROM  `t2` AS g2
    WHERE g2.usignal = 1 AND g2.type = 1
)

/*dynamic other join query here */
and id>=1 /*dynamic conditional query here*/
order by id desc limit 0,20

That working well if data is small, But my data is bigger and that fail while execute

How can i do that thanks

Edit:
What about my sql? Is that make execute slowly and make it timeout?

Edit02:
I using phpmyadmin and click index to t1(id, signal) and t2(type, unsignal)
And i add id primary key fo both table example in http://www.sqlfiddle.com/#!2/d88a9/1
But in real my tables have about 10 column. And i using left join but that's still timeout :(

Upvotes: 0

Views: 777

Answers (6)

Gar
Gar

Reputation: 862

Index t1 on signal, and t2 on (usignal,utype).

Define your primary keys as well.

Upvotes: 0

CM.
CM.

Reputation: 1047

Do you have any indices? Make sure that you created the proper ones.

For t1 it seems that you need an index on (id, signal) tuple. For t2 you need an index on (usignal, type) tuple.

This is how you can add them if you already don't have (according to the create tables you don't):

create index 'id_signal_index' on t1 (`id`, `signal`);
create index 'id_usignal_index' on t2 (`usignal`, `type`);

It is usually a good practice to have primary key for id with auto increment in a table like t1.

Also convert the inner query into left join query, which is explained in other answers.

Upvotes: 0

bjelli
bjelli

Reputation: 10070

In your SQL-Fiddle http://www.sqlfiddle.com/#!2/ee61b/3 there is an option down below in the green navigation bar: "+ view execution plan". You can also get to this information by adding "EXPLAIN" to the front of your query.

In you case the result looks something like this:

+------+--------------+-------------+--------+---------------+--------------+---------+------+------+-------------+
| id   | select_type  | table       | type   | possible_keys | key          | key_len | ref  | rows | Extra       |
+------+--------------+-------------+--------+---------------+--------------+---------+------+------+-------------+
|    1 | PRIMARY      | g1          | ALL    | NULL          | NULL         | NULL    | NULL |    4 | Using where |
|    2 | UNION        | g1          | ALL    | NULL          | NULL         | NULL    | NULL |    4 |             |
|    2 | UNION        | <subquery3> | eq_ref | distinct_key  | distinct_key | 4       | func |    1 |             |
|    3 | MATERIALIZED | g2          | ALL    | NULL          | NULL         | NULL    | NULL |    4 | Using where |
| NULL | UNION RESULT | <union1,2>  | ALL    | NULL          | NULL         | NULL    | NULL | NULL |             |
+------+--------------+-------------+--------+---------------+--------------+---------+------+------+-------------+

Look at the column "possible_keys": you have NULL everywhere. That is bad, it means that the database has to search sequentially through your data to find something.

If you add the right primary keys and indexes to your database, then every search will be done using a clever data structure like a tree, and will be much faster, especially for large date:

+------+--------------+------------+--------+-----------------+---------+---------+-------------+------+-------------+
| id   | select_type  | table      | type   | possible_keys   | key     | key_len | ref         | rows | Extra       |
+------+--------------+------------+--------+-----------------+---------+---------+-------------+------+-------------+
|    1 | PRIMARY      | g1         | ref    | signal          | signal  | 5       | const       |    2 |             |
|    2 | UNION        | g2         | ref    | PRIMARY,usignal | usignal | 5       | const       |    2 | Using where |
|    2 | UNION        | g1         | eq_ref | PRIMARY         | PRIMARY | 4       | test.g2.uid |    1 |             |
| NULL | UNION RESULT | <union1,2> | ALL    | NULL            | NULL    | NULL    | NULL        | NULL |             |
+------+--------------+------------+--------+-----------------+---------+---------+-------------+------+-------------+

So: read up on Primary Keys and Indexes and apply this knowledge to your example.

Upvotes: 0

M Khalid Junaid
M Khalid Junaid

Reputation: 64466

Try to get rid of your sub query and use join , i have also removed the union from the query and for this i have enclosed the conditions in braces to meet your union needs

SELECT g1.* FROM `t1` AS g1
left join `t2` AS g2 on (g1.id=g2.uid)
WHERE (
(g2.usignal = 1 AND g2.type = 1 )
 OR g1.signal = 1      
  )
order by id desc limit 0,20

Also make sure you have proper index on your columns

See this fiddle

Upvotes: 1

calcinai
calcinai

Reputation: 2617

Have you tried joining instead of that nested select (which won't be fast)?

SELECT g1.* FROM `t1` AS g1
LEFT JOIN `t2` AS g2 ON g2.uid = g1.id 
WHERE g1.signal = 1
 OR (g2.usignal = 1 AND g2.type = 1)

/*dynamic other join query here */

and id>=1 /*dynamic conditional query here*/
order by id desc limit 0,20

Upvotes: 0

Radu Sua
Radu Sua

Reputation: 3

What error do you get so that we can answer your question .. you can set the maximum execution time from php ini like this :ini_set('max_execution_time', 300); And your task will work for 300 seconds instead of 30 .

Upvotes: 0

Related Questions