SQL Server : counter for insert,update,delete & select queries - sql-server-2008

I am a newbie to SQL Server. In MySQL to find the count of the insert, update, delete, select queries we have the below queries:
SELECT
mysql> SHOW GLOBAL STATUS like '%com_select%';
+-------------+-----+
| Variable_name | Value |
+-------------+-----+
| Com_select | 1 |
+-------------+-----+
1 row in set (0.00 sec)
INSERT
mysql> SHOW GLOBAL STATUS like '%com_insert%';
+-----------------+-----+
| Variable_name | Value |
+-----------------+-----+
| Com_insert | 0 |
| Com_insert_select | 0 |
+-----------------+-----+
2 rows in set (0.00 sec)
UPDATE
mysql> SHOW GLOBAL STATUS like '%com_update%';
+----------------+-----+
| Variable_name | Value |
+----------------+-----+
| Com_update | 0 |
| Com_update_multi | 0 |
+----------------+-----+
2 rows in set (0.00 sec)
DELETE
mysql> SHOW GLOBAL STATUS like '%com_delete%';
+----------------+-----+
| Variable_name | Value |
+----------------+-----+
| Com_delete | 0 |
| Com_delete_multi | 0 |
+----------------+-----+
2 rows in set (0.00 sec)
Similarly are there any equivalent queries to find the count of the insert, update, delete, select queries in SQL Server?
Thanks !!!
Edit : A SQL server performance counter sys.dm_os_performance_counters provides the Page reads/sec & writes/sec like wise there anyother counters that can provide insert,update,delete counts?

Related

How to use Limit in query on my index column without scan all rows?

Here is my table :
In my table
Clustering_key (Primary key and auto incremental)
ID (Index Column)
Data (Text datatype column)
Position(Index column) maintain the order of Data
My table have 90,000 rows with same ID equal to 5. I want to first 3 rows with ID equal to 5 and my query like this
Select * from mytable where ID=5 Limit 3;
ID column is index column So I think mysql scan only first 3 rows but mysql scan around 42000 rows.
Here Explain query :
Any possibility to avoid all rows scan.
Please give me some solution
Thanks in advance
I simulated the scenario.
Created the table using
CREATE TABLE mytable (
Clustering_key INT NOT NULL AUTO_INCREMENT,
ID INT NOT NULL,
Data text NOT NULL,
Position INT NOT NULL,
PRIMARY KEY (Clustering_key),
KEY(ID),
KEY(Position)
)
Inserted data with
INSERT INTO mytable (ID,Data,Position) VALUES (5,CONCAT("Data-",5), 7);
INSERT INTO mytable (ID,Data,Position) VALUES (5,CONCAT("Data-",5), 26);
INSERT INTO mytable (ID,Data,Position) VALUES (5,CONCAT("Data-",51), 27);
INSERT INTO mytable (ID,Data,Position) VALUES (5,CONCAT("Data-",56), 28);
INSERT INTO mytable (ID,Data,Position) VALUES (5,CONCAT("Data-",57), 31);
Explain
mysql> explain Select * from mytable where ID=5 Limit 3
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
| 1 | SIMPLE | mytable | NULL | ref | ID | ID | 4 | const | 5 | 100.00 | NULL |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
Yes, the explain shows rows examined is 5, but not 3.
But seems it is just a misleading info.
The exact number of run-time rows_examined can be verified by enabling slow log for all queries(Setting long_query_time=0) by following steps.
Note: You MUST set long_query_time=0 only in your own testing database. And you MUST reset the parameter back to the previous value after the testing.
- set GLOBAL slow_query_log=1;
- set global long_query_time=0;
- set session long_query_time=0;
mysql> show variables like '%slow%';
+---------------------------+-------------------------------------------------+
| Variable_name | Value |
+---------------------------+-------------------------------------------------+
| log_slow_admin_statements | OFF |
| log_slow_slave_statements | OFF |
| slow_launch_time | 2 |
| slow_query_log | ON |
| slow_query_log_file | /usr/local/mysql/data/slow.log |
+---------------------------+-------------------------------------------------+
5 rows in set (0.10 sec)
mysql> select ##long_query_time;
+-------------------+
| ##long_query_time |
+-------------------+
| 0.000000 |
+-------------------+
And then in the terminal, executing the query
<pre>
mysql> Select * from mytable where ID=5 Limit 3;
+----------------+----+---------+----------+
| Clustering_key | ID | Data | Position |
+----------------+----+---------+----------+
| 5 | 5 | Data-5 | 7 |
| 26293 | 5 | Data-5 | 26 |
| 26294 | 5 | Data-51 | 27 |
+----------------+----+---------+----------+
3 rows in set (0.00 sec)
mysql> Select * from mytable where ID=5 Limit 1;
Checking the slow log by inspecting the slow_query_log_file printed above /usr/local/mysql/data/slow.log
You can find out the info as below.
# Time: 2019-04-26T01:48:19.890846Z
# User#Host: root[root] # localhost [] Id: 5124
# Query_time: 0.000575 Lock_time: 0.000146 Rows_sent: 3 Rows_examined: 3
SET timestamp=1556243299;
Select * from mytable where ID=5 Limit 3;
# Time: 2019-04-26T01:48:34.672888Z
# User#Host: root[root] # localhost [] Id: 5124
# Query_time: 0.000182 Lock_time: 0.000074 Rows_sent: 1 Rows_examined: 1
SET timestamp=1556243314;
Select * from mytable where ID=5 Limit 1;
The runtime Rows_exmained value is equal to the value of limit parameter.
The test is done on MySQL 5.7.18.
----------------------------------Another way to verify----------------------------------
mysql> show status like '%Innodb_rows_read%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| Innodb_rows_read | 13 |
+------------------+-------+
1 row in set (0.00 sec)
mysql> Select * from mytable where ID=5 Limit 1;
+----------------+----+--------+----------+
| Clustering_key | ID | Data | Position |
+----------------+----+--------+----------+
| 5 | 5 | Data-5 | 7 |
+----------------+----+--------+----------+
1 row in set (0.00 sec)
mysql> show status like '%Innodb_rows_read%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| Innodb_rows_read | 14 |
+------------------+-------+
1 row in set (0.00 sec)
You can see the Innodb_rows_read just be increased 1 for limit 1.
If you do a full table scan query, you can see the value will be increased by the count of the table.
mysql> select count(*) from mytable;
+----------+
| count(*) |
+----------+
| 126296 |
+----------+
1 row in set (0.05 sec)
mysql> show status like '%Innodb_rows_read%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| Innodb_rows_read | 505204 |
+------------------+--------+
1 row in set (0.00 sec)
mysql> Select * from mytable where Data="Data-5";
+----------------+----+--------+----------+
| Clustering_key | ID | Data | Position |
+----------------+----+--------+----------+
| 5 | 5 | Data-5 | 7 |
| 26293 | 5 | Data-5 | 26 |
| 26301 | 5 | Data-5 | 7 |
+----------------+----+--------+----------+
3 rows in set (0.09 sec)
mysql> show status like '%Innodb_rows_read%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| Innodb_rows_read | 631500 |
+------------------+--------+
1 row in set (0.00 sec)
Both ways confirmed the explain for limit seems providing misleading info about rows examined.

Mysql. Update not null column with null value

mysql> SHOW COLUMNS from users LIKE 'created_at';
+------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| created_at | datetime | NO | | NULL | |
+------------+----------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'innodb_strict_mode';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| innodb_strict_mode | ON |
+--------------------+-------+
1 row in set (0.00 sec)
mysql> UPDATE `users` SET `created_at` = NULL WHERE `users`.`id` = 200;
Query OK, 1 row affected, 1 warning (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 1
mysql> SELECT `created_at` from `users` WHERE `users`.`id` = 200;
+---------------------+
| created_at |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)
Is it normal behavior? Just warning.
Yes, it can be normal behavior. It depends on server's SQL Mode. It is possible that database is not in strict mode, and zero-dates are allowed.
See more details on this page - Server SQL Modes: STRICT_ALL_TABLES, STRICT_TRANS_TABLES, NO_ZERO_DATE.
Check current SQL mode using this query -
SHOW VARIABLES WHERE variable_name = 'sql_mode';

How to empty or clean some of the system variables value after mysql database is rebuild?

For testing, I almost rebuild the newly designed MySQL database every day recently, I also have a Php application based on that. For my understanding, some of system variables value has been accumulated in every rebuild, such as:
mysql> show global status like '%tmp%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 14062 |
| Created_tmp_files | 437 |
| Created_tmp_tables | 20854 |
+-------------------------+-------+
3 rows in set (0.00 sec)
Created_tmp_disk_tables and Created_tmp_tables are growing constantly based on every rebuild. Surely there are some other variables doing same thing. I wonder how can we clean them safely in every rebuild, so we won't be cheated by these values. We will see the real value.
Please feel free to let me know if the question is not clear. Thanks.
after testing #dwjv's suggestion, doing 'flush status', got:
mysql> flush status;
Query OK, 0 rows affected (0.02 sec)
mysql> show global status like '%tmp%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 14062 |
| Created_tmp_files | 0 |
| Created_tmp_tables | 20856 |
+-------------------------+-------+
3 rows in set (0.00 sec)
The variable 'Created_tmp_files' was cleaned, but other two didn't change.
'Flush status' will only reset the session status, some, but not all the global status variables.
mysql> show status like '%tmp%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 0 |
| Created_tmp_files | 0 |
| Created_tmp_tables | 0 |
+-------------------------+-------+
3 rows in set (0.00 sec)
Then I followd &Yak's suggestion 'service mysql restart', got:
mysql> show global status like '%tmp%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 14062 |
| Created_tmp_files | 0 |
| Created_tmp_tables | 20857 |
+-------------------------+-------+
3 rows in set (0.00 sec)
Still same, no change.
All you need to do is restart the server.
FLUSH STATUS;
This will flush many of the global variables.

What is the difference between queries and questions in mysql

I would like to know the difference between below two values in mysql.
show status like 'queries' ;
+---------------+-------------+
| Variable_name | Value |
+---------------+-------------+
| Queries | 16987383643 |
+---------------+-------------+
1 row in set (0.00 sec)
mysql> show status like 'Questions' ;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Questions | 5 |
+---------------+-------+
1 row in set (0.00 sec)
Try looking in the manual?
13.7.5.37. SHOW STATUS Syntax
5.1.5. Server Status Variables
unlike the Queries variable. This [Questions] variable does not count COM_PING, COM_STATISTICS, COM_STMT_PREPARE, COM_STMT_CLOSE, or COM_STMT_RESET commands.

SQL_NO_CACHE does not work

The first time I run this sql, needs 39 seconds,when I run again and increase SQL_NO_CACHE,does not seem to take effect:
mysql> select count(*) from `deal_expired` where `site`=8&&`area`=122 &&
endtime<1310444996056;
+----------+
| count(*) |
+----------+
| 497 |
+----------+
1 row in set (39.55 sec)
mysql> select SQL_NO_CACHE count(*) from `deal_expired` where `site`=8&&`area`=
122 && endtime<1310444996056;
+----------+
| count(*) |
+----------+
| 497 |
+----------+
1 row in set (0.16 sec)
I tried a variety of methods, here
and even restart the mysql server or change table name, but I still can not let 39 seconds run this SQL
I replaced another SQL, and an increase in the first run on SQL_NO_CACHE, the problem is the same:
mysql> select SQL_NO_CACHE count(*) from `deal_expired` where `site`=25&&`area`=
134 && endtime<1310483196227;
+----------+
| count(*) |
+----------+
| 315 |
+----------+
1 row in set (2.17 sec)
mysql> select SQL_NO_CACHE count(*) from `deal_expired` where `site`=25&&`area`=
134 && endtime<1310483196227;
+----------+
| count(*) |
+----------+
| 315 |
+----------+
1 row in set (0.01 sec)
What is the reason?
How can I get the same SQL run-time?
I want to find a way to optimize this SQL to perform 39 seconds
BTW: RESET QUERY CACHE FLUSH QUERY CACHE FLUSH TABLES SET SESSION query_cache_type=off does not work
mysql state cache has been closed:
mysql> SHOW STATUS LIKE "Qcache%";
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Qcache_free_blocks | 0 |
| Qcache_free_memory | 0 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 0 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 0 |
+-------------------------+-------+
8 rows in set (0.04 sec)
mysql> select count(*) from `deal_expired` where `site`=25&&`area`=134 && endtime<1310
483196227;
+----------+
| count(*) |
+----------+
| 315 |
+----------+
1 row in set (0.01 sec)
mysql> SHOW STATUS LIKE "Qcache%";
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Qcache_free_blocks | 0 |
| Qcache_free_memory | 0 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 0 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 0 |
+-------------------------+-------+
8 rows in set (0.00 sec)
explan this SQL,used site+endtime composite index(named site_endtime):
mysql> explain select count(*) from `deal_expired` where `site`=8&&`area`=122 && endti
me<1310444996056;
+--------+------+-------------------------------+--------------+---------+------
-+------+-------------+
| table | type | possible_keys | key | key_len | ref
| rows | Extra |
+--------+------+-------------------------------+--------------+---------+------
-+------+-------------+
| deal_expired | ref | name,url,endtime,site_endtime | site_endtime | 4 | const
| 353 | Using where |
+--------+------+-------------------------------+--------------+---------+------
-+------+-------------+
1 row in set (0.00 sec)
The first query should use SQL_NO_CACHE to tell MySQL not to put the result into the cache. The second query uses the cache and the tells MySQL not to cache the result of that query, which does nothing.
tl;dr - Reverse your queries.
The answer to "How can I get the same SQL run-time?" is - you cannot.
If your query reads some rows, they are cached, dependent on the storage engine in use, those rows are either in OS cache (myisam), or in buffer pool (innodb). If rows are cached, running the same query second time is much faster, because MySQL does not have to read from the disk.
I was under the impression that including any sort of SQL function that is calculated in the current runtime would not cache. Have you tried doing something like the following?
select count(*), now() from `deal_expired` where `site`=8&&`area`=122 && endtime<1310444996056;
see: http://forums.mysql.com/read.php?24,225286,225468#msg-225468
you could try RESET QUERY CACHE (you need the RELOAD privilege) although having just read the link above this will probably not work either :(