BREAKING: Kyle Rittenhouse Not Guilty on All Counts

https://cdn0.thetruthaboutguns.com/wp-content/uploads/2021/10/AP21278681741615-scaled.jpg

Kyle rittenhouse verdict kenosha trial
(Mark Hertzberg/Pool Photo via AP)

Next Post Coming Soon…▶

A jury in Kenosha, Wisconsin has found Kyle Rittenhouse

Rittenhouse was standing guard outside a car dealership in Kenosha on August 25 last year during riots that followed the shooting of Jacob Blake. Police did little or nothing to curb the violence and destruction.

When Rittenhouse attempted to stop a crowd from setting a dumpster on fire, he was approached by a violent Joseph Rosenbaum. That set off the entire chain of events leading to today’s result.

Rittenhouse was threatened and attacked that night by four convicted felons that night; a mentally ill pedophile, car thief and forger, a domestic abuser, and a burglar who assaulted his own grandmother.

One attacker threatened to kill him and tried to take Rittenhouse’s rifle. One delivered a flying kick as he layed on the ground. Another struck him on the head and neck with a skateboard. The last one pointed a gun at him.

Gaige Grosskreutz Rittenhouse Kenosha shooting

Rittenhouse used the AR-15 rifle he was carrying to shoot three of his attackers, killing two.

The trial of the 18-year-old Rittenhouse inevitably became a political football. The inept prosecution succeeded in depicting, almost as well as the defense, that in each of the shootings, Rittenhouse had defended himself from physical threats or imminent attacks. Yet the media have been slanting and shading their reports of the testimony, no matter how frustratingly exculpatory it was.

Rittenhouse was portrayed as a racist and a white supremacist, despite everyone involved in the incident that night being a white male.

The jury had to weigh not only the evidence, but also the knowledge that if they found Rittenhouse not guilty of some or all of the charges, it could result in more rioting. Wisconsin Governor Tony Evers put 500 National Guardsman on standby in anticipation of the verdict. If he’d bothered to do that during the rioting in Kenosha last year, it’s likely that none of this would have happened.

 

Next Post Coming Soon…▶

The Truth About Guns

Kyle Rittenhouse: Not Guilty, All Charges

As I said all along.

Hey, Twitter! Told you so. Are you going to unblock me now, or will you doxx and ban the unanimous jury members, too?

Self defense is a human right.

 

Carl is an unpaid TZP volunteer. If you found this post useful, please consider dropping something in his tip jar. He could really use the money, what with ISP bills, site hosting and SSL certificate, new 2021 model hip, and general life expenses.Click here to donate via PayPal.
(More Tip Jar Options)

FacebooktwitterredditpinteresttumblrmailThe Zelman Partisans

Kyle Rittenhouse NOT Guilty On All Charges! ~ Verdict VIDEO

https://www.ammoland.com/wp-content/uploads/2021/11/Kyle-Rittenhouse-Not-Guilty-500×295.jpg

H/T to Law and Crime TV for the week-long live Video feed.

KENOSHA, WI-(Ammoland.com)-  After three days of deliberation, the jury in the Kyle Rittenhouse self-defense trial returned a verdict of not guilty on all charges.

Kyle Rittenhouse Not Guilty on All Charges

The jurors found that Kyle Rittenhouse was justified in his self-defense shooting of three attackers. The jury believed that the three men targeted Rittenhouse, and the jury thought that he had felt that the three men threatened his life. The jury took four days to decide Mr. Rittenhouse’s fate.

The first man attacked Kyle Rittenhouse after he put out a fire in a dumpster. Joseph Rosenbaum, a convicted pedophile, attacked and chased Rittenhouse through a car lot. After Rosenbaum pursued Rittenhouse through the parking lot, he turned and fired his AR-15 and killed Rosenbaum.

An angry mob chased Rittenhouse down the street. He stumbled and fell to the ground as he tried to evade the mob and get to the police. The second man shot was Anthony Huber. Mr. Huber was a domestic abuser and attacked Rittenhouse with a skateboard. Rittenhouse shot and killed Huber.

The third man didn’t die but was shot in the arm. Gaige Grosskreutz pointed a loaded Glock at Mr. Rittenhouse while he was on the ground. Rittenhouse pointed his AR-15 at Mr. Grosskreutz. He put up his hands, and Rittenhouse didn’t pull the trigger of his rifle until Grosskreutz pointed his pistol at Rittenhouse. Grosskreutz was hit in the arm and was disarmed by the shot.

Grosskreutz admitted on the stand that Rittenhouse didn’t fire until he leveled the Glock at him. This moment was a critical turning point in the case, and some legal experts believed that Grosskreutz comment doomed the prosecution’s case.

Rittenhouse also took the stand to defend himself. Rittenhouse broke down in tears when walking the court through the actions of the fateful night. The court had to adjourn to give Mr. Rittenhouse time to recover from emotional testimony. Rittenhouse came off as believable.

The prosecution cross-examined Rittenhouse for hours. The prosecutor came off as a bully. The prosecutor attacked Mr. Rittenhouse for exercising his right to remain silent. This attack provoked a stinging rebuke from the judge. He removed the jury from the court and ripped into the prosecution for questioning Mr. Rittenhouse’s use of a Constitutional right. The attack by the prosecution almost caused a mistrial.

Gun rights groups have celebrated the verdict. They believe that this decision is a victory for self-defense. Alan Gottlieb, the founder of the Second Amendment Foundation, claims that this is a victory for the Second Amendment.

“The verdict by the Kenosha jury is an affirmation that people, regardless of their age, have a right to defend themselves against violent attack, by individuals or a mob,” Gottlieb said.

“Anyone who viewed the video evidence and listened to the testimony would easily conclude Kyle Rittenhouse acted in self-defense. Fortunately, this young man’s supporters were able to raise the funds necessary for mounting a first-class defense. But this was a high-profile case, and ample financial resources became available. What about lower-profile cases where people with limited resources find themselves unable to afford adequate legal counsel.

“There is no doubt this case will be analyzed and debated for months, or even years. What the verdict demonstrates is that reasonable people sitting in judgment of a case that should never have been brought in the first place can see through a politically-motivated prosecution and reach a verdict that is both reasonable and just.”

Kyle Rittenhouse will now move on with his life and is in our prayers.


About John Crump

John is a NRA instructor and a constitutional activist. John has written about firearms, interviewed people of all walks of life, and on the Constitution. John lives in Northern Virginia with his wife and sons and can be followed on Twitter at @crumpyss, or at www.crumpy.com.

John Crump

AmmoLand.com

The 9 Best Data Visualization Methods That Adds Value to Any Reports

https://static1.makeuseofimages.com/wordpress/wp-content/uploads/2021/11/Data-Visualization-Methods-Featured-Image.jpeg

Professional data analysts use data visualization techniques like graphs, charts, and maps to create reports from numerical data. These visual elements help others understand the patterns, trends, and outliers in any data set.

By knowing and applying the best data visualization techniques, you can also enhance your project reports. Read on to become your own data analyst or learn more about the mathematical visualization of data.

1. Choropleth Map

You can use a choropleth map to visualize geographical location-related data. You’ll need to use a color gradient to show the decreasing or increasing data values as the color fades or deepens.

This data visualization technique enables you to see the change of data variables from one region to another. You can use this technique to visualize population density, employment rate, etc. If you want to find out the country-wise consumption of your services or content, this technique is also useful.

You’ll find the Google Data Studio Geo Chart element handy for creating choropleth maps. You can add your data to Google Sheets and then import that to the Google Data Studio to create different views of your choropleth map. Furthermore, you’ll also get an interactive graphic that shows the underlying data when you hover your mouse cursor over any region of the map.

MAKEUSEOF VIDEO OF THE DAY

2. Bar Chart

Bar charts are crucial to visualize data comparisons between multiple components of the data. For example, comparing revenue from financial quarters or years is the most common application.

You need to place the categories that you want to compare on one axis. On the other axis, you need to keep the measured values. Depending on the values of this second axis, the length of the bars will vary.

You can make your bar charts more informative by adding different colors, 3D effects, legends, interactive data views, etc. Google Data Studio offers you multiple forms of bar charts. You can choose from column/stacked column, bar/stacked bar, etc.

3. 3D Maps

3D maps are essentially charts made of bars or columns on a geographical map. You could use this type of chart to flaunt your knack for tech when presenting reports to the audience. 3D maps are ideal for data sets related to products, services, or population data that links a specific region on the globe.

Microsoft Excel has an elaborate feature for creating such cool pictorial data visualizations. It’s called Microsoft 3D Maps. You’ll find it on the Insert tab of the Excel ribbon.

4. Sankey Diagram

This data visualization technique is appropriate to show how data flows. A plain text or rectangle box represents the entities or nodes of your data set. Arcs or arrows of different widths represent the link between the above nodes.

The width of the arrows or arcs is directly proportional to the importance of the data flow. Therefore, this chart is helpful to visualize large data sets related to the flow of resources like energy, money, time, etc., in a project.

5. Network Graphs

You can show the relationship between multiple entities by creating a network graph. On a network graph, nodes or vertices represent each entity. Edges or links represent the connection between these nodes.

You can use network graphs to find patterns, anomalies, and insights from large data sets that connect multiple entities. Alternatively, you can use a network graph to resolve any bottleneck around project tasks and subtasks by linking all resources and statuses.

6. Timeline Charts

Timeline charts help you visualize events or tasks in chronological order. It has wide applications in managing multiple tasks and projects. The involved persons can effortlessly identify project progress or bottlenecks when you visualize task-related data in timeline charts.

Typically, timeline charts are linear. The key events, tasks, and subtasks show up on the axis. You can also make your timelines more attractive by inserting graphics, thumbnail-view of documents, linked resources, milestones, deadlines, etc.

Gantt charts are streamlined timeline charts. You’ll find many free-to-use Gantt chart templates in the Microsft Excel templates library. You may select any template that matches your project and tweak that a bit to make comprehensive project timelines.

Related: How to Make a Scatter Plot in Excel and Present Your Data

7. Treemap Chart

Treemap chart comes from the renowned information visualization and computing method treemapping. Visualization of large hierarchical data sets takes place on nested rectangles. Your data looks highly organized in branches and sub-branches.

You need a data set with two quantitative values for each product or service because the rectangles visualize two data values. A treemap chart is ideal for visualizing a massive data set with many attributes on one screen.

The color and dimension of each rectangle are directly related to the underlying values. Therefore, spotting anomalies or patterns becomes truly easy if you create treemaps for large data sets.

8. Spiral Chart

Spiral charts efficiently visualize large data sets on a single screen. You can show the underlying data as points, columns, or lines. You can also color code the data for easy visualization.

Typically, you need to put the start point of your data at the center of the spiral and move outward as your data grows. Spiral plots are ideal for visualizing the following data: yearly student attendance, employee attendance, products sold, website traffic, etc.

9. Pyramid Chart

Pyramid charts are ideal if you need to visualize data sets in a hierarchy. You’ll see different pyramid charts with a lot of visual effects. However, it’s simply a triangle with different sections separated by lines.

These separated sections of the triangle usually have different heights and widths. The value of the underlying data defines the volume of the separated sections. Usually, the high volume or wider sections should contain a general topic.

The section with the least volume should contain a niche topic from the general topic sitting at the bottom. You can create pyramid charts to better understand your business model, products sold, customer segment, etc.

Get Valuable Insights From Your Data

These are the commonly used data visualization techniques that cover a wide variety of data sets. You can easily create any of the above charts or graphs by practicing a few times. If you’re a learner, these are the appropriate mathematical data interpretation techniques to get started.

While you’re applying the above techniques in your work or school, also know that Google Data Studio helps you make great data visualizations in a few clicks.

The 8 Best Features of Google Data Studio for Data Analysis and Visualization

Want to impress your audience with actionable data insights and compelling visualizations? Check out these Google Data Studio features.

Read Next

About The Author

Tamal Das
(211 Articles Published)

Tamal is a freelance writer at MakeUseOf. After gaining substantial experience in technology, finance, and business processes in his previous job in an IT consulting company, he adopted writing as a full-time profession 3 years ago. While not writing about productivity and the latest tech news, he loves to play Splinter Cell and binge-watch Netflix/ Prime Video.

More
From Tamal Das

Subscribe to our newsletter

Join our newsletter for tech tips, reviews, free ebooks, and exclusive deals!

Click here to subscribe

MUO – Feed

Crowder Reacts to Verdict: Kyle Rittenhouse is NOT GUILTY!

https://www.louderwithcrowder.com/media-library/image.png?id=28000388&width=980

The system has been against Kyle Rittenhouse from the beginning. The media has been lying about him, the prosecution played dirty tricks, and the judge and jury were targeted. But even after all that, Kyle Rittenhouse has been found not guilty on all charges!


NOT GUILTY!!! Crowder REACTS To Rittenhouse Verdict! | Louder With Crowder

youtu.be

"I want the criminals to be more afraid of us than we are of them[…] That is exactly what this verdict says."

"You think the people who were prepared to riot and burn stuff down outside of Kenosha, not only now, maybe–give it a second thought[…] because they realize a jury of their peers said ‘enough, enough. You don’t get to burn shit down, consequence-free’."

Today, America can let out a sigh of relief, knowing the right to defend oneself is still intact. The moral courage of the jury as they finally decided to stand up to the ignorant leftist mob is something that cannot be understated. God bless them.

Get your content free from Big Tech’s filter. Bookmark this website and sign up for our newsletter!

Louder With Crowder

Rioters Flee In Terror As Kyle Rittenhouse Emerges From Courthouse With AR-15

https://media.babylonbee.com/articles/article-9956-1.jpg

KENOSHA, WI—As the Rittenhouse trial drew to a close, Antifa rioters were preparing their violent destruction of the city. But their plans were quickly foiled as Rittenhouse emerged from the courthouse a free man, AR-15 in hand. 

“The jig is up! Scatter!” cried the terrified commie waifs as they skittered toward shadowy alleyways like cockroaches. “The Rittenhouse has returned! Judgment is upon us! RUN FOR YOUR LIVES!” 

Rittenhouse then appeared to descend the courthouse steps in slow motion, surrounded by a flock of doves and a heavenly golden light. At the terrifying sight, hundreds of Antifa fairies and murderous pedophiles shrieked in terror like a den of goblins, crawling into various holes and cracks in the earth. 

“Waaaaaaaaa! Cried the prosecuting attorneys,” knowing their career was over forever. “We’re ruined! Ruined by the unstoppable power of Kyle Rittenhouse!” 

Sources say that once Rittenhouse has completed his task of purging the land of evil and wickedness, he will return home to his mother, who confirmed he is grounded for a week. 


Ghostbusters Catch Ghosts That Ruin Progressive Narrative

Subscribe to The Babylon Bee on YouTube


The Babylon Bee

How Triggers May Significantly Affect the Amount of Memory Allocated to Your MySQL Server

https://www.percona.com/blog/wp-content/uploads/2021/11/Triggers-Affect-Memory-Allocated-to-Your-MySQL-Server-300×157.pngTriggers Affect Memory Allocated to Your MySQL Server

Triggers Affect Memory Allocated to Your MySQL ServerMySQL stores active table descriptors in a special memory buffer called the table open cache. This buffer is controlled by configuration variables table_open_cache that hold the maximum number of table descriptors that MySQL should store in the cache, and table_open_cache_instances that stores the number of the table cache instances. With default values of table_open_cache=4000 and table_open_cache_instances=16, MySQL will create 16 independent memory buffers that will store 250 table descriptors each. These table cache instances could be accessed concurrently, allowing DML to use cached table descriptors without locking each other.

If you use only tables, the table cache does not require a lot of memory because descriptors are lightweight, and even if you significantly increase the value of the table_open_cache, the required memory amount would not be so high. For example, 4000 tables will take up to 4000 x 4K = 16MB in the cache, 100.000 tables will take up to 390MB that is also not quite a huge number for this number of tables.

However, if your tables have triggers, it changes the game.

For the test I created a table with a single column and inserted a row into it:

mysql> CREATE TABLE tc_test( f1 INT);
Query OK, 0 rows affected (0,03 sec)

mysql> INSERT INTO tc_test VALUES(1);
Query OK, 1 row affected (0,01 sec)

Then I flushed the table cache and measured how much memory it uses:

mysql> FLUSH TABLES;
Query OK, 0 rows affected (0,02 sec)mysql> SHOW GLOBAL STATUS LIKE 'Open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   |     2 |
+---------------+-------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/TABLE_SHARE::mem_root';
+---------------+
| current_alloc |
+---------------+
|     60.50 KiB |
+---------------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
Empty set (0,00 sec)

Then I accessed the table to put it into the cache.

$ for i in `seq 1 1 16`; do mysql test -e "SELECT * FROM tc_test"; done
...

mysql> SHOW GLOBAL STATUS LIKE 'Open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   |    20 |
+---------------+-------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/TABLE_SHARE::mem_root';
+---------------+
| current_alloc |
+---------------+
|     75.17 KiB |
+---------------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
Empty set (0,01 sec)

16 table descriptors took less than 16 KiB in the cache.

Now let’s try to create some triggers on this table and see if it changes anything.

mysql> CREATE TRIGGER tc_test_ai AFTER INSERT ON tc_test FOR EACH ROW 
    -> BEGIN 
    ->   SIGNAL SQLSTATE '45000' SET message_text='Very long string. 
    ->     MySQL stores table descriptors in a special memory buffer, called table open cache. 
    ->     This buffer could be controlled by configuration variables table_open_cache that 
    ->     holds how many table descriptors MySQL should store in the cache and table_open_cache_instances 
    ->     that stores the number of the table cache instances. So with default values of table_open_cache=4000 
    ->     and table_open_cache_instances=16, you will have 16 independent memory buffers that will store 250 
    ->     table descriptors each. These table cache instances could be accessed concurrently, allowing DML 
    ->     to use cached table descriptors without locking each other. If you use only tables, the table cache 
    ->     does not require a lot of memory, because descriptors are lightweight, and even if you significantly 
    ->     increased the value of table_open_cache, it would not be so high. For example, 4000 tables will take 
    ->     up to 4000 x 4K = 16MB in the cache, 100.000 tables will take up to 390MB that is also not quite a huge 
    ->     number for this number of open tables. However, if your tables have triggers, it changes the game.'; 
    -> END|

Then let’s flush the table cache and test memory usage again.

Initial state:

mysql> FLUSH TABLES;
Query OK, 0 rows affected (0,00 sec)

mysql> SHOW GLOBAL STATUS LIKE 'Open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   |     2 |
+---------------+-------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/TABLE_SHARE::mem_root';
+---------------+
| current_alloc |
+---------------+
|     60.50 KiB |
+---------------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
Empty set (0,00 sec)

After I put the tables into the cache:

$ for i in `seq 1 1 16`; do mysql test -e "SELECT * FROM tc_test"; done
...

mysql> SHOW GLOBAL STATUS LIKE 'Open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   |    20 |
+---------------+-------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/TABLE_SHARE::mem_root';
+---------------+
| current_alloc |
+---------------+
|     75.17 KiB |
+---------------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
+---------------+
| current_alloc |
+---------------+
|    611.12 KiB |
+---------------+
1 row in set (0,00 sec)

As a result, in addition to 75.17 KiB in the table cache, 611.12 KiB is occupied by the memory/sql/sp_head::main_mem_root. That is the "Mem root for parsing and representation of stored programs."

This means that each time when the table is put into the table cache, all associated triggers are put into the memory buffer, storing their definitions.

FLUSH TABLES command clears the stored programs cache as well as the table cache:

mysql> FLUSH TABLES;
Query OK, 0 rows affected (0,01 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
Empty set (0,00 sec)

More triggers increase memory usage when put into the cache.

For example, if we create five more triggers and repeat our test we will see the following numbers:

mysql> \d |
mysql> CREATE TRIGGER tc_test_bi BEFORE INSERT ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000
' SET message_text='Very long string. MySQL stores table descriptors in a special memory buffer, calle
at holds how many table descriptors MySQL should store in the cache and table_open_cache_instances t
hat stores the number of the table cache instances. So with default values of table_open_cache=4000
and table_open_cache_instances=16, you will have 16 independent memory buffers that will store 250 t
able descriptors each. These table cache instances could be accessed concurrently, allowing DML to u
se cached table descriptors without locking each other. If you use only tables, the table cache doe
s not require a lot of memory, because descriptors are lightweight, and even if you significantly increased the value of table_open_cache, it would not be so high. For example, 4000 tables will take u
p to 4000 x 4K = 16MB in the cache, 100.000 tables will take up to 390MB that is also not quite a hu
ge number for this number of open tables. However, if your tables have triggers, it changes the gam
e.'; END|
Query OK, 0 rows affected (0,01 sec)

mysql> CREATE TRIGGER tc_test_bu BEFORE UPDATE ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000
' SET message_text='Very long string. MySQL stores table descriptors in a special memory buffer, calle
at holds how many table descriptors MySQL should store in the cache and table_open_cache_instances t
hat stores the number of the table cache instances. So with default values of table_open_cache=4000
and table_open_cache_instances=16, you will have 16 independent memory buffers that will store 250 t
able descriptors each. These table cache instances could be accessed concurrently, allowing DML to u
se cached table descriptors without locking each other. If you use only tables, the table cache doe
s not require a lot of memory, because descriptors are lightweight, and even if you significantly increased the value of table_open_cache, it would not be so high. For example, 4000 tables will take u
p to 4000 x 4K = 16MB in the cache, 100.000 tables will take up to 390MB that is also not quite a hu
ge number for this number of open tables. However, if your tables have triggers, it changes the gam
e.'; END|
Query OK, 0 rows affected (0,02 sec)

mysql> CREATE TRIGGER tc_test_bd BEFORE DELETE ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET message_text='Very long string. MySQL stores table descriptors in a special memory buffer, calle
at holds how many table descriptors MySQL should store in the cache and table_open_cache_instances that stores the number of the table cache instances. So with default values of table_open_cache=4000
and table_open_cache_instances=16, you will have 16 independent memory buffers that will store 250 table descriptors each. These table cache instances could be accessed concurrently, allowing DML to use cached table descriptors without locking each other. If you use only tables, the table cache does not require a lot of memory, because descriptors are lightweight, and even if you significantly increased the value of table_open_cache, it would not be so high. For example, 4000 tables will take up to 4000 x 4K = 16MB in the cache, 100.000 tables will take up to 390MB that is also not quite a huge number for this number of open tables. However, if your tables have triggers, it changes the game.'; END|
Query OK, 0 rows affected (0,01 sec)

mysql> CREATE TRIGGER tc_test_au AFTER UPDATE ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000'
SET message_text='Very long string. MySQL stores table descriptors in a special memory buffer, call
ed ta a
t holds how many table descriptors MySQL should store in the cache and table_open_cache_instances th
at stores the number of the table cache instances. So with default values of table_open_cache=4000 a
nd table_open_cache_instances=16, you will have 16 independent memory buffers that will store 250 ta
ble descriptors each. These table cache instances could be accessed concurrently, allowing DML to us
e cached table descriptors without locking each other. If you use only tables, the table cache does
not require a lot of memory, because descriptors are lightweight, and even if you significantly increased the value of table_open_cache, it would not be so high. For example, 4000 tables will take up
to 4000 x 4K = 16MB in the cache, 100.000 tables will take up to 390MB that is also not quite a hug
e number for this number of open tables. However, if your tables have triggers, it changes the game
.'; END|
Query OK, 0 rows affected (0,01 sec)

mysql> CREATE TRIGGER tc_test_ad AFTER DELETE ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000'
SET message_text='Very long string. MySQL stores table descriptors in a special memory buffer, call
ed table open cache. This buffer could be controlled by configuration variables table_open_cache tha
t holds how many table descriptors MySQL should store in the cache and table_open_cache_instances th
at stores the number of the table cache instances. So with default values of table_open_cache=4000 a
nd table_open_cache_instances=16, you will have 16 independent memory buffers that will store 250 ta
ble descriptors each. These table cache instances could be accessed concurrently, allowing DML to us
e cached table descriptors without locking each other. If you use only tables, the table cache does
not require a lot of memory, because descriptors are lightweight, and even if you significantly increased the value of table_open_cache, it would not be so high. For example, 4000 tables will take up
to 4000 x 4K = 16MB in the cache, 100.000 tables will take up to 390MB that is also not quite a hug
e number for this number of open tables. However, if your tables have triggers, it changes the game
.'; END|
Query OK, 0 rows affected (0,01 sec)

mysql> SHOW GLOBAL STATUS LIKE 'Open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables | 35 |
+---------------+-------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/TABLE_SHARE::mem_root';
+---------------+
| current_alloc |
+---------------+
| 446.23 KiB |
+---------------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
+---------------+
| current_alloc |
+---------------+
| 3.58 MiB |
+---------------+
1 row in set (0,00 sec)

Numbers for the event memory/sql/sp_head::main_mem_root differ six times:

mysql> SELECT 3.58*1024/611.12;
+------------------+
| 3.58*1024/611.12 |
+------------------+
|         5.998691 |
+------------------+
1 row in set (0,00 sec)

Note that the length of the trigger definition affects the amount of memory allocated by the memory/sql/sp_head::main_mem_root.

For example, if we define the triggers as follow:

mysql> DROP TABLE tc_test;
Query OK, 0 rows affected (0,02 sec)

mysql> CREATE TABLE tc_test( f1 INT);
Query OK, 0 rows affected (0,03 sec)

mysql> INSERT INTO tc_test VALUES(1);
Query OK, 1 row affected (0,01 sec)

mysql> \d |
mysql> CREATE TRIGGER tc_test_ai AFTER INSERT ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000'
SET message_text='Short string';end |
Query OK, 0 rows affected (0,01 sec)

mysql> CREATE TRIGGER tc_test_au AFTER UPDATE ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000'
SET message_text='Short string';end |
Query OK, 0 rows affected (0,04 sec)

mysql> CREATE TRIGGER tc_test_ad AFTER DELETE ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000'
SET message_text='Short string';end |
Query OK, 0 rows affected (0,01 sec)

mysql> CREATE TRIGGER tc_test_bi BEFORE INSERT ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000'
SET message_text='Short string';end |
Query OK, 0 rows affected (0,01 sec)

mysql> CREATE TRIGGER tc_test_bu BEFORE UPDATE ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000'
SET message_text='Short string';end |
Query OK, 0 rows affected (0,02 sec)

mysql> CREATE TRIGGER tc_test_bd BEFORE DELETE ON tc_test FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000'
SET message_text='Short string';end |
Query OK, 0 rows affected (0,01 sec)

mysql> \d ;
mysql> FLUSH TABLES;
Query OK, 0 rows affected (0,00 sec)

mysql> SHOW GLOBAL STATUS LIKE 'Open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   |     2 |
+---------------+-------+
1 row in set (0,01 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/TABLE_SHARE::mem_root';
+---------------+
| current_alloc |
+---------------+
|     60.50 KiB |
+---------------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
Empty set (0,00 sec)

$ for i in `seq 1 1 16`; do mysql test -e "select * from tc_test"; done
...

mysql> SHOW GLOBAL STATUS LIKE 'Open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   |    35 |
+---------------+-------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/TABLE_SHARE::mem_root';
+---------------+
| current_alloc |
+---------------+
|    446.23 KiB |
+---------------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
+---------------+
| current_alloc |
+---------------+
|      1.89 MiB |
+---------------+
1 row in set (0,00 sec)

The resulting amount of memory is 1.89 MiB instead of 3.58 MiB for the longer trigger definition.

Note that having a single table cache instance requires less memory to store trigger definitions. E.g. for our small six triggers, it will be 121.12 KiB instead of 1.89 MiB:

mysql> SHOW GLOBAL VARIABLES LIKE 'table_open_cache_instances';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| table_open_cache_instances |     1 |
+----------------------------+-------+
1 row in set (0,00 sec)

mysql> FLUSH TABLES;
Query OK, 0 rows affected (0,00 sec)

mysql> SHOW GLOBAL STATUS LIKE 'Open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   |     2 |
+---------------+-------+
1 row in set (0,00 sec)

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
Empty set (0,00 sec)

$ for i in `seq 1 1 16`; do mysql test -e "select * from tc_test"; done
...

mysql> SELECT current_alloc FROM sys.memory_global_by_current_bytes 
    -> WHERE event_name='memory/sql/sp_head::main_mem_root';
+---------------+
| current_alloc |
+---------------+
| 121.12 KiB |
+---------------+
1 row in set (0,00 sec)

Conclusion

When you access tables that have associated triggers, their definitions are put into the stored programs cache even when not fired. This was reported at MySQL Bug #86821 and closed as “Not a Bug” by Oracle. This is, certainly, not a bug, but the table and stored routines cache design. Still, it is good to be prepared, so you are not surprised when you run short of memory faster than you expect. Especially if you have many triggers with long definitions.

Percona Database Performance Blog