Why do we need importance sampling? Let's say we want to calculate the following expectation:
$$
\mathbb{E}_{z\sim p_z(z)}[f(z)]
$$
One issue, is that the samples from $p_z(z)$ could be not very informative:

We see here that $f(z)$ only takes on non-zero values near the edges of $p_z(z)$.
We we can solve this by using importance sampling, which will take more samples from regions with non-zero contribution.
What I don't understand is why we would want to use importance sampling. I.e., the samples of $z$ that cause $f(z)$ to be zero are going to drag down the expectation towards zero, which seems good since indeed, for most values of $z$, $f(z)$ will be zero.
Note, I'm assuming that the expectation is a single value and roughly, the expression means: "The expected value of $f(z)$ when we randomly sample from $p_z(z)$ is $E$", where $E$ is a single number.

Let me give you a very simple example. Assume that $p$ is a standard Gaussian and that $f : x \mapsto 10^{8} \cdot \mathbf{1}_{x \geq 5}$. Then the expectation you're trying to compute is $10^8 \cdot \mathbb{P}(X \geq 5) \approx 28.7$. The intuition that the expectation will be $0$ because $f$ is 0 in the important regions of $p$ is wrong. If $f$ has extremely large values in regions of small mass under $p$ then you may have an expectation that is far from $0$.
With this in mind, of course if you use standard Monte Carlo to approximate this expectation, your estimates will be 0 almost all the time even if you use $100000$ samples to compute each MC estimate. This is quite far from $28.7$.
Meanwhile, if you do importance sampling with proposal $\mathcal{N}(5, 1)$ you get much much better estimates, as I illustrate through the following snippet. I estimate the root mean square error of such estimates by computing n_rep estimates.
from torch.distributions import Normal
from scipy.stats import norm 

n_samples = 5000
n_rep = 1000
f = lambda x : 10.**8 * (x >= 5)
p = Normal(0., 1.)
q = Normal(5., 1.)

p_samples = p.sample((n_rep, n_samples))
q_samples = p_samples + 5

#Monte Carlo estimates, sampling from p
mc = f(p_samples).mean(-1)

#Importance Sampling estimates, sampling from q
log_weights = p.log_prob(q_samples) - q.log_prob(q_samples) #importance weights
IS = (f(q_samples) * log_weights.exp()).mean(-1)

print(f'Expectation value: {10**8 * (1 - norm.cdf(5))}')
print(f'RMSE Monte Carlo estimates: {mc.std()}')
print(f'RMSE IS estimates: {IS.std()}')

The code returns
Expectation value: 28.66515719235352
RMSE Monte Carlo estimates: 632.4555053710938
RMSE IS estimates: 0.9297240972518921

In short, importance sampling is very useful when you don't know how to sample from the distribution $p$ but it is also as much useful when you want to estimate "rare events" as is the case here.
