Retrieve data from MySQL table stored as milliseconds - mysql

I have a field named premium_end_date, and I run a query to retrieve a date that is smaller than premium_end_daten, the field records are stored as milliseconds:
mysql> SELECT id_prem, premium_end_date FROM ads_premium LIMIT 1;
+---------+------------------+
| id_prem | premium_end_date |
+---------+------------------+
| 1 | 1633967568 |
+---------+------------------+
1 row in set (0.00 sec)
The table looks like:
mysql> describe ads_premium;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id_prem | int unsigned | NO | PRI | NULL | auto_increment |
| premium_views | bigint | YES | | NULL | |
| premium_start_date | bigint | YES | | NULL | |
| premium_end_date | bigint | YES | | NULL | |
+--------------------+--------------+------+-----+---------+----------------+
10 rows in set (0.03 sec)
I run this query:
/** code here */
WHERE premium_end_date >= CURDATE()
/** code here */
But as the record is in milliseconds, it does not return anything, and I do not want to change the field from bigint to another one, as I have a lot of data inside

That looks like a straight forward unix timestamp to me.
If you run,
SELECT FROM_UNIXTIME(1633967568);
Do you get a date like 2021-10-11 15:52:48
So you can select using
WHERE FROM_UNIXTIME(premium_end_date) >= CURRENT_TIMESTAMP()

Related

Performance problem in MySQL - Sum() and select is taking too long

i have a performance problem in MySQL.
I have a table with 215000 rows (InnoDB Engine) inserted in it and to execute the function SUM() on one column for only 1254 rows is taking 500ms.
The version i am using is : MySQL 5.7.32
The computer specs are the following:
Core I5 3.0 Ghz
8 Gb Ram
Solid State Drive
Here i leave information about the structure of the database:
mysql> select count(*) from cuenta_corriente;
+----------+
| count(*) |
+----------+
| 214514 |
+----------+
mysql> describe cuenta_corriente;
+-----------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+-------------+------+-----+---------+----------------+
| ID_CUENTA_CORRIENTE | int(11) | NO | PRI | NULL | auto_increment |
| ID_CLIENTE | int(11) | YES | MUL | NULL | |
| ID_PROVEEDOR | int(11) | YES | MUL | NULL | |
| FECHA | varchar(50) | YES | MUL | NULL | |
| FECHA_FISCAL | varchar(50) | YES | | NULL | |
| ID_OPERACION | int(11) | YES | MUL | NULL | |
| ID_TIPO_OPERACION | int(11) | YES | MUL | NULL | |
| DEBE | double | YES | | 0 | |
| HABER | double | YES | | 0 | |
| TOTAL | double | YES | | 0 | |
| SALDO_ANTERIOR | double | YES | | 0 | |
| SALDO_ACTUAL | double | YES | | 0 | |
| ID_OPERACION_ASOCIADA | int(11) | YES | | NULL | |
| ELIMINADO | int(11) | YES | | 0 | |
| ID_EMPLEADO | int(11) | NO | | 0 | |
+-----------------------+-------------+------+-----+---------+----------------+
show indexes from cuenta_corriente;
+------------+------------------------------------------------------------+
| Non_unique | Key_name Column_name |
+------------+------------------------------------------------------------+
| 0 | PRIMARY ID_CUENTA_CORRIENTE |
| 1 | IDX_CUENTA_CORRIENTE ID_CLIENTE |
| 1 | IX_cuenta_corriente_FECHA FECHA |
| 1 | IX_cuenta_corriente_ID_CLIENTE ID_CLIENTE |
| 1 | IX_cuenta_corriente_ID_PROVEEDOR ID_PROVEEDOR |
| 1 | IX_cuenta_corriente_ID_TIPO_OPERACION ID_TIPO_OPERACION |
| 1 | IX_cuenta_corriente_ID_OPERACION ID_OPERACION |
| 1 | IDX_cuenta_corriente_ID_OPERACION ID_OPERACION |
+------------+------------------------------------------------------------+
8 rows in set (0.00 sec)
The problem is with the folowing queries, in my opinion they are taking too long, considering that i have an index for the column ID_CLIENTE and that there are only 1254 rows with the ID_CLIENTE column = 19. Here are the query results:
mysql> SELECT COUNT(*) FROM CUENTA_CORRIENTE WHERE ID_CLIENTE = 19;
1254 rows
mysql> SELECT DEBE FROM CUENTA_CORRIENTE WHERE ID_CLIENTE = 19;
1254 rows - 0.513 sec
mysql> SELECT SUM(DEBE) FROM CUENTA_CORRIENTE WHERE ID_CLIENTE = 19;
0.582 sec
The strange thing is if i select all the columns instead selecting only the "DEBE" column, it takes less time:
mysql> SELECT * FROM CUENTA_CORRIENTE WHERE ID_CLIENTE = 19;
0.095 sec
Can anyone help me to improve the performance?
You can make just that query fast by creating a composite index to support it.
ie:
CREATE INDEX IDX_QUERY_FAST ON cuenta_corriente (ID_CLIENTE, DEBE)
But don't forget, each index has to be maintained, so it slows down any inserts into the table, so you don't want 200 indexes supporting every possible query.
With the existing index, the engine should be smart enough to identify the 1200 rows you care about using the index, but then it has to go read all the table records (across however many pages) that have the individual rows to get the DEBE column.
Add this index to help most of the queries you have shown:
INDEX(ID_CLIENTE, DEBE)
and drop INDEX(ID_CLIENTE) if you have such.
Are all of your secondary indexes starting with the PRIMARY KEY?? (The names imply such; please provide SHOW CREATE TABLE to definitively say what columns are in each index.) Don't start an index with the PK; it is likely to be useless.
Run EXPLAIN SELECT ... to see which index a query uses.
When timing a query, run it twice. The first run may spend extra time loading index or data rows into cache (in RAM in the buffer_pool); the second run may be significantly faster because of the caching.

MySQL - i dont see data, but mysql says, that there are rows

I have table ip_per_nat_vlan, innodb format. When I give truncate table, table is empty.
Then I have php script, which fill data into this table.
When is this script finished without errors (simple insert statemets) situation is following:
select * from ip_per_nat_vlan;
Empty set (0.00 sec)
.
select count(*) from ip_per_nat_vlan;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)
.
show table status;
+----------------------------------+--------+---------+------------+----------+----------------+-------------+-----------------+--------------+------------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+----------------------------------+--------+---------+------------+----------+----------------+-------------+-----------------+--------------+------------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| ip_per_nat_vlan | InnoDB | 10 | Dynamic | 141291 | 100 | 14172160 | 0 | 6832128 | 25165824 | 143563 | 2017-12-24 16:26:40 | 2018-06-13 09:01:33 | NULL | utf8_unicode_ci | NULL |
MySQL says, that there should be 14172160 rows, but I dont see any. Where could be a problem? Transactions? But I dont see any running thread and no any fault.
Thank you. D
Structure of table is:
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ipAddress | varchar(255) | NO | UNI | NULL | |
| nat | int(11) | NO | | NULL | |
| vlan | int(11) | NO | | NULL | |
| district | varchar(255) | YES | | NULL | |
| idOblasti | int(11) | YES | | NULL | |
| type | varchar(255) | NO | | NULL | |
| macAddress | varchar(255) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
There are various ways to "count" rows in a table.
The normal way. Just count them.
select count(*) as table_rows from table_name ;
Accuracy: 100% accurate count at the time of the query is run.
using the information_schema tables
select table_rows
from information_schema.tables
where table_schema = 'database_name'
and table_name = 'table_name' ;
Accuracy: Only an approximation. If the table is the target of frequent inserts and deletes, the result can be way off the actual count. This can be improved by running ANALYZE TABLE more often.
Efficiency: Very good, it doesn't touch the table at all.
As count option is 100% accurate, your table doesn't contain any data.
Check your code and default commit option of MySQL.
Looks like you are inserting rows, but not committing them, check your index length.
Check more details here
https://dba.stackexchange.com/questions/151769/mysql-difference-between-using-count-and-information-schema-tables-for-coun
First thing, I am not sure how mysql run this line and produce the result
select count() from ip_per_nat_vlan
count() will return [Err] 1064.
count(*) or else a field name should be mentioned inside.

MySQL gives incorrect DateTime Value for some dates but not others

I have a table that looks like this in MySQL:
mysql> describe sale;
+-------------+------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------+------+-----+-------------------+-----------------------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| timestamp | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| salesperson | int(11) | NO | MUL | NULL | |
| customer | int(11) | NO | MUL | NULL | |
| product | int(11) | NO | MUL | NULL | |
| count | int(11) | NO | | NULL | |
+-------------+------------+------+-----+-------------------+-----------------------------+
Now if a run this statement, I get an ERROR 1292:
mysql> insert into `sale` values (25860,'2006-04-02 02:30:50',1,25,2,21);
ERROR 1292 (22007): Incorrect datetime value: '2006-04-02 02:30:50' for column 'timestamp' at row 1
However, if I just change the date by one day, the statement works:
mysql> insert into `sale` values (25860,'2006-04-03 02:30:50',1,25,2,21);
Query OK, 1 row affected (0.00 sec)
What is the magical thing about the second of April 2006? I can't detect any problems with the format specified. I also tried retyping the statement to make sure it was not caused by invisible characters.
Daylight Saving Time.
On 2006-04-02 at 2am the clock jumped to 3am. So there was no 02:30:50

Create table with date column

I want to create a student table with column 'student_birthday' and its format should be dd-mm-yy.
create table `student`.`studentinfo`(
`student_id` int(10) not null auto_increment,
`student_name` varchar(45) not null,
`student_surname` varchar(45) not null,
`student_birthday` date(???),
(some lines of code)
primary key(student_id));
what should be inputted in the (???) to get the right format above?
Just use "DATE" without the brackets. The brackets are only needed for certain column types where you want to specify the maximum number of bytes/characters that can be stored.
For MySQL, it's documented at https://dev.mysql.com/doc/refman/5.7/en/date-and-time-types.html
The following example will explain your problem. I am using MySQL 5.7.18.
Firstly I have described the structure of users table as I am going to create posts table with FOREIGN KEY.
Later I created posts table and it has a DATE field named created with many other columns.
Finally I inserted 1 row in the newly created table.
mysql> desc users;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| id | bigint(20) | NO | PRI | NULL | |
| fname | varchar(50) | NO | | NULL | |
| lname | varchar(50) | NO | | NULL | |
| uname | varchar(20) | NO | | NULL | |
| email | text | NO | | NULL | |
| contact | bigint(12) | NO | | NULL | |
| profile_pic | text | NO | | NULL | |
+-------------+-------------+------+-----+---------+-------+
7 rows in set (0.00 sec)
mysql> CREATE TABLE posts(id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, title text NOT NULL, description text NOT NULL, posted_by bigint, FOREIGN KEY(posted_by) REFERENCES users(id) ON DELETE CASCADE ON UPDATE RESTRICT , created DATE);
Query OK, 0 rows affected (0.01 sec)
mysql> desc posts;
+-------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| title | text | NO | | NULL | |
| description | text | NO | | NULL | |
| posted_by | bigint(20) | YES | MUL | NULL | |
| created | date | YES | | NULL | |
+-------------+------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> INSERT INTO posts(title, description, posted_by, created) values("Getting started with MySQL", "Excellent Database system", 1, "2017-05-26");
Query OK, 1 row affected (0.00 sec)
mysql> select * from posts;
+----+----------------------------+---------------------------+-----------+------------+
| id | title | description | posted_by | created |
+----+----------------------------+---------------------------+-----------+------------+
| 1 | Getting started with MySQL | Excellent Database system | 1 | 2017-05-26 |
+----+----------------------------+---------------------------+-----------+------------+
1 row in set (0.00 sec)
mysql>
The datatype date on its own is enough to represent a date value. The format will matter when you are displaying the data, for which you can use the FORMAT function on your date column.
I should add that there is a certain amount of flexibility as to the format when inserting date time literals as documented here.

mysql query sub selecting group by

I have a table described below
mysql> describe payments;
+----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(128) | NO | | NULL | |
| email | varchar(128) | NO | | NULL | |
| txn_id | varchar(19) | NO | | NULL | |
| payment_status | varchar(20) | NO | | NULL | |
| auth | varchar(40) | NO | | NULL | |
| expired_at | datetime | YES | | NULL | |
+----------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
It is possible that I could have 2 entries such as:
name: chris|expires at: 2012-01-01|email: me#chrismuench.com
name: chris|expires at: 2014-01-01|email: me#chrismuench.com
I want to do a query that I find all expired users based on downloads. But there could be multiple entires for the same email address. In the above case this person should NOT show up in the expired list.
It seems like I want to do a GROUP BY email but somehow filter out expiration if it is > NOW()
It would seem that for each unique user you want the maximum date and to check whether that is before NOW() right? So:
SELECT name, MAX(expired_at) as latest_expired FROM payments WHERE lastest_expired < NOW() GROUP BY name;
Here is what you would have to do. I haven't used datetime functions in a bit so you'll have to double check it for correctness. I just assumed NOW() was a function.
Find the set of unexpired users, then subtract it from the entire set of users.
select * from table where email not in (select email from table where expired_at > NOW());