Представим, что у нас есть таблица пользователей (users) или заказов (orders) на десятки миллионов записей и больше. И у нас стоит задача их перебора в любом контексте.
Я представляю себе это в виде цикла, в котором порционно забираем разумное количество записей, что-то вроде:
select * from users order by id limit 1000 offset 0;
Такой запрос выполняется очень быстро, моментально.
Рано или поздно мы приходим к offset, например 40 млн:
select * from users order by id limit 1000 offset 40000000;
И тут запрос может выполняться несколько минут.
Происходит это из-за того, что mysql не может гарантировать, что все элементы будут на своих порядковых местах, ведь может так статься, что элемент 40 000 099 был ранее удален и алгоритмам приходится сканировать все 40 млн элементов для получения выборки.
Решением этой проблемы может стать видоизменение запроса из limit-offset на where-limit:
select * from users where id > 40000000 order by id limit 1000;
Выполняется моментально!
И даже, если не все элементы гарантированно присутствуют в таблице, айдишник для where легко «вытащить» из предыдущего запроса в цепочке.
Microsoft SQL Server Express Edition — бесплатная версия Microsoft SQL Server, в которой многий функционал порезан.
Например отсутствует SQL Server Agent или Maintenance Plans, которые облегчают создание автоматических бэкапов баз данных.
В связи с этим, приходится выбирать другие пути. Один из них описан ниже.
Исходные данные для наших настроек:
имя базы данных: db_name
путь для хранения скриптов и бэкапов базы данных db_name: «d:\projects\db_backups»
периодичность создания бэкапов: раз в 1 день
срок хранения бекапов: 3 дня
Разделим скрипт бекапов на 2 шага:
создание и сохранение бекапа
очистка папки от старых бэкапов
Для первого шага:
a) Запускаем нижеследующий скрипт, например в Management Studio, чтобы записалась хранимая процедура на master базе данных
USE [master]
GO
/****** Object: StoredProcedure [dbo].[sp_BackupDatabases] Script Date: 8/12/2021 6:26:34 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Microsoft
-- Create date: 2010-02-06
-- Description: Backup Databases for SQLExpress
-- Parameter1: databaseName
-- Parameter2: backupType F=full, D=differential, L=log
-- Parameter3: backup file location
-- =============================================
CREATE PROCEDURE [dbo].[sp_BackupDatabases]
@databaseName sysname = null,
@backupType CHAR(1),
@backupLocation nvarchar(200)
AS
SET NOCOUNT ON;
DECLARE @DBs TABLE
(
ID int IDENTITY PRIMARY KEY,
DBNAME nvarchar(500)
)
-- Pick out only databases which are online in case ALL databases are chosen to be backed up
-- If specific database is chosen to be backed up only pick that out from @DBs
INSERT INTO @DBs (DBNAME)
SELECT Name FROM master.sys.databases
where state=0
AND name= ISNULL(@databaseName ,name)
ORDER BY Name
-- Filter out databases which do not need to backed up
IF @backupType='F'
BEGIN
DELETE @DBs where DBNAME IN ('tempdb','Northwind','pubs','AdventureWorks')
END
ELSE IF @backupType='D'
BEGIN
DELETE @DBs where DBNAME IN ('tempdb','Northwind','pubs','master','AdventureWorks')
END
ELSE IF @backupType='L'
BEGIN
DELETE @DBs where DBNAME IN ('tempdb','Northwind','pubs','master','AdventureWorks')
END
ELSE
BEGIN
RETURN
END
-- Declare variables
DECLARE @BackupName nvarchar(100)
DECLARE @BackupFile nvarchar(300)
DECLARE @DBNAME nvarchar(300)
DECLARE @sqlCommand NVARCHAR(1000)
DECLARE @dateTime NVARCHAR(20)
DECLARE @Loop int
-- Loop through the databases one by one
SELECT @Loop = min(ID) FROM @DBs
WHILE @Loop IS NOT NULL
BEGIN
-- Database Names have to be in [dbname] format since some have - or _ in their name
SET @DBNAME = '['+(SELECT DBNAME FROM @DBs WHERE ID = @Loop)+']'
-- Set the current date and time n yyyyhhmmss format
SET @dateTime = REPLACE(CONVERT(VARCHAR, GETDATE(),101),'/','') + '_' + REPLACE(CONVERT(VARCHAR, GETDATE(),108),':','')
-- Create backup filename in path\filename.extension format for full,diff and log backups
IF @backupType = 'F'
SET @BackupFile = @backupLocation+REPLACE(REPLACE(@DBNAME, '[',''),']','')+ '_FULL_'+ @dateTime+ '.BAK'
ELSE IF @backupType = 'D'
SET @BackupFile = @backupLocation+REPLACE(REPLACE(@DBNAME, '[',''),']','')+ '_DIFF_'+ @dateTime+ '.BAK'
ELSE IF @backupType = 'L'
SET @BackupFile = @backupLocation+REPLACE(REPLACE(@DBNAME, '[',''),']','')+ '_LOG_'+ @dateTime+ '.TRN'
-- Provide the backup a name for storing in the media
IF @backupType = 'F'
SET @BackupName = REPLACE(REPLACE(@DBNAME,'[',''),']','') +' full backup for '+ @dateTime
IF @backupType = 'D'
SET @BackupName = REPLACE(REPLACE(@DBNAME,'[',''),']','') +' differential backup for '+ @dateTime
IF @backupType = 'L'
SET @BackupName = REPLACE(REPLACE(@DBNAME,'[',''),']','') +' log backup for '+ @dateTime
-- Generate the dynamic SQL command to be executed
IF @backupType = 'F'
BEGIN
SET @sqlCommand = 'BACKUP DATABASE ' +@DBNAME+ ' TO DISK = '''+@BackupFile+ ''' WITH INIT, NAME= ''' +@BackupName+''', NOSKIP, NOFORMAT'
END
IF @backupType = 'D'
BEGIN
SET @sqlCommand = 'BACKUP DATABASE ' +@DBNAME+ ' TO DISK = '''+@BackupFile+ ''' WITH DIFFERENTIAL, INIT, NAME= ''' +@BackupName+''', NOSKIP, NOFORMAT'
END
IF @backupType = 'L'
BEGIN
SET @sqlCommand = 'BACKUP LOG ' +@DBNAME+ ' TO DISK = '''+@BackupFile+ ''' WITH INIT, NAME= ''' +@BackupName+''', NOSKIP, NOFORMAT'
END
-- Execute the generated SQL command
EXEC(@sqlCommand)
-- Goto the next database
SELECT @Loop = min(ID) FROM @DBs where ID>@Loop
END
b) В папке бэкапов создаем исполняемый файл с расширение bat (например, sql_db_backup.bat) и содержимым
Калькулятор хостится на Digital Ocean, сервер на Centos 7, Python + Dash фреймворк для визуализации.
С данным реальным примером, можно начать увлекательное путешествие в мир финансовой грамотности, попутно, ознакомившись с языком Питон, который идеально подходит под задачи автоматизации математических вычислений, а так же фреймворком Даш (на основе более известного фреймворка Flask c элементами ReactJS, но это все под капотом)
Принцип работ инвестиций в дивидендные акции
Один из самых интересных и надежных способов получать пассивный доход — это инвестиции в надежные дивидендные акции.
Наиболее оправданный подход (проверенный годами и многими публичными пассивными инвесторами) — это вкладывать регулярно (например раз в месяц или раз в неделю) одинаковыми суммами в понятные и надежные компании, которые годами наращивают свою выручку и, соответсвенно, дивиденды.
Далее, эти растущие дивиденды ре-инвестируются, что увеличивает регулярные пополнения. Машина раскручивается, и капитал растет.
Все это происходит по экспоненте, как можно убедиться после использования данного калькулятора.
Установка окружения для нашего проекта и размещение на хостинге, публикация.
Подразумевается, что хостинг приобретен, операционная система установлена, веб сервер настроен (или же вы работаете на локальномкомпьютере на Mac или Linux)
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from app import app
app.layout = html.Div([
html.Label(children="Hello world"),
])
server = app.server
app.config.suppress_callback_exceptions = True
if __name__ == '__main__':
app.run_server(debug=True)
Сохраняем CTRL+O и закрываем редактор CRTL+X
Теперь мы готовы запускать нашу тестовую среду (более подробную документацию на английском языке, если это понадобится, можно найти здесь)
# gunicorn --bind 0.0.0.0:8000 index:server
Наше страничка «Hello world» доступна по адресу
http://{ip_адрес_сервера}:8000
Если успешно запустили, дезактивируем виртуальную среду
# deactivate
и приступаем к настройкам веб-сервера (коим в нашем примере небезызвестный Caddy), чтобы калькулятор был доступен по доменному имени.
Первым делом создаем .service файл в папке /etc/systemd/system
И, последним делом, осталось дать понять, где искать наш сервис веб-серверу. В случае с Caddy это делается максимально просто, плюс с коробки получаем сертификат
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from app import app
from apps import home, dividends_calculator
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content')
])
server = app.server
app.config.suppress_callback_exceptions = True
@app.callback(Output('page-content', 'children'),
[Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/':
return home.layout
elif pathname == '/dividends-calculator':
return dividends_calculator.layout
else:
return '404'
if __name__ == '__main__':
app.run_server(debug=True)
# nano app.py
Вставляем код ниже и сохраняем
#from flask import Flask
import dash
import dash_core_components as dcc
import dash_html_components as html
print(dcc.__version__) # 0.6.0 or above is required
external_css = ["https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css",
"https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css",
"https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css",
"https://fonts.googleapis.com/css?family=Raleway:400,300,600",
"https://codepen.io/chriddyp/pen/bWLwgP.css",
"https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"]
app = dash.Dash(external_stylesheets=external_css)
# mkdirs apps && cd apps
# nano __init__.py
Оставляем его пустым и сохраняем.
Далее
# nano commonmodules.py
Вставляем код ниже и сохраняем
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
def get_header():
header = html.Div([
html.Div([
html.H1(
'List of Dashes')
], className="twelve columns padded"),
], className="gs-text-header")
return header
def get_menu():
menu = html.Div([
dcc.Link('Home ', href='/', className="p-2 text-dark"),
dcc.Link('Dividends Calculator ', href='/dividends-calculator', className="p-2 text-dark")
], className="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm")
return menu
# nano home.py
Вставляем код ниже и сохраняем
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from apps import commonmodules
from app import app
layout = html.Div([
commonmodules.get_menu(),
html.H1('This is home screen'),
html.A('My blog', href='https://questpro.club')
])
# nano dividends_calculator.py
Вставляем код ниже и сохраняем
# -*- coding: utf-8 -*-
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from apps import commonmodules
from app import app
meta_tags = [
{'name':'description',
'content':'Дивидендный калькулятор с учетом сложного процента'},
{'name':'title',
'content':'Дивидендный калькулятор'}
]
#app.external_stylesheets = external_stylesheets
app.meta_tags = meta_tags
app.title = 'Дивидендный калькулятор'
bottom_text = '''
1) Все суммы в долларах, проценты - в %
2) По умолчанию, средний размер дивидентов при покупке акций устанавливаем в 4%, можно поменять
3) По умолчанию, средний рост цены акций в год устанавливаем в 12.5% на основе статистики по S&P Dividends aristocrats
4) Все дивиденды реинвестируем для осуществления скорейшего роста - сложный процент
'''
default__divident_income_per_month = 1000
default__start_capital = 1000
default__regular_payment = 1000
default__start_divident_percent = 4
default__average_cost_grow_percent = 12.5
layout = html.Div([
commonmodules.get_menu(),
html.H1('Дивидендный калькулятор с учетом сложного процента'),
html.Div([
html.Div([
html.Div([], className="col-sm-1"),
html.Label(children='Желаемый средний доход в месяц по дивидентам ($)', className="col-sm-4 col-form-label"),
html.Div([
dcc.Input(id='divident-income-per-month', value='1000', type='text', className="form-control-plaintext")
], className="col-sm-4")
], className="form-group row"),
html.Div([
html.Div([], className="col-sm-1"),
html.Label(children='Первоначальный взнос ($)', className="col-sm-4 col-form-label"),
html.Div([
dcc.Input(id='start-capital', value='1000', type='text', className="form-control-plaintext")
], className="col-sm-4")
], className="form-group row"),
html.Div([
html.Div([], className="col-sm-1"),
html.Label(children='Частота очередного поступления: 1 месяц', className="col-sm-4 col-form-label")
], className="form-group row"),
html.Div([
html.Div([], className="col-sm-1"),
html.Label(children='Размер очередного поступления ($)', className="col-sm-4 col-form-label"),
html.Div([
dcc.Input(id='regular-payment', value='1000', type='text', className="form-control-plaintext")
], className="col-sm-4")
], className="form-group row"),
html.Div([
html.Div([], className="col-sm-1"),
html.Label(children='Средний размер дивидентов в при покупке акций (%)', className="col-sm-4 col-form-label"),
html.Div([
dcc.Input(id='start-divident-percent', value='4', type='text', className="form-control-plaintext")
], className="col-sm-4")
], className="form-group row"),
html.Div([
html.Div([], className="col-sm-1"),
html.Label(children='Средний рост цены акций в год (%)', className="col-sm-4 col-form-label"),
html.Div([
dcc.Input(id='average-cost-grow-percent', value='12.5', type='text', className="form-control-plaintext")
], className="col-sm-4")
], className="form-group row"),
html.Div([
html.Div([], className="col-sm-1"),
html.Label(children='Отображаем на графиках максимум лет', className="col-sm-4 col-form-label"),
], className="form-group row"),
dcc.Slider(
id='maximum-years',
min=10,
max=50,
marks={i: 'рассматриваем максимум лет {}'.format(i) if i == 1 else str(i) for i in range(5, 51)},
value=11
),
html.Div([
html.Div([], className="col-sm-1"),
html.Label(id='result', className="col-sm-8 col-form-label"),
], className="form-group row")
], className=""),
html.Div([
dcc.Graph(id='dividends-graph'),
dcc.Graph(id='capital-graph')
]),
html.Div([
dcc.Markdown(children=bottom_text)
])
])
def create_dividends_graph(df, target, title):
return {
'data': [dict(
x=df['month'],
y=df['dividend_no_reinv'],
mode='lines',
name='Дивиденды - без реинвестиций и без роста цены акций'
), dict(
x=df['month'],
y=df['dividend_percent_reinv'],
mode='lines',
name='Дивиденды - рост за счет роста акций'
), dict(
x=df['month'],
y=df['dividend_all_reinv'],
mode='lines',
name='Дивиденды - рост цен акций и реинвестирование дивидендов'
), dict(
x=[target['month'],],
y=[target['dividend'],],
mode='marks',
name='Целевое значение дивидендов'
)],
'layout': {
'annotations': [{
'x': 0, 'y': 0, 'xanchor': 'left', 'yanchor': 'bottom',
'xref': 'paper', 'yref': 'paper', 'showarrow': False,
'align': 'left', 'bgcolor': 'rgba(255, 255, 255, 0.5)',
'text': title
}],
'yaxis': {'type': 'linear', 'title': 'Дивиденды в месяц, $'},
'xaxis': {'showgrid': True, 'title': 'Месяцы'}
}
}
def create_capital_graph(df, target, title):
return {
'data': [dict(
x=df['month'],
y=df['cap_no_reinv'],
mode='lines',
name='Капитал - вложенные деньги'
), dict(
x=df['month'],
y=df['cap_percent_reinv'],
mode='lines',
name='Капитал - с ростом цены акций'
), dict(
x=df['month'],
y=df['cap_all_reinv'],
mode='lines',
name='Капитал - с ростом цены акций и реинвестицией дивидендов'
)],
'layout': {
'annotations': [{
'x': 0, 'y': 0, 'xanchor': 'left', 'yanchor': 'bottom',
'xref': 'paper', 'yref': 'paper', 'showarrow': False,
'align': 'left', 'bgcolor': 'rgba(255, 255, 255, 0.5)',
'text': title
}],
'yaxis': {'type': 'linear', 'title': 'Капитал, $'},
'xaxis': {'showgrid': True, 'title': 'Месяцы'}
}
}
def total_result_div(result):
if result['dividend'] <= 0:
return "Желаемая дивидендная доходность не найдена в заданном промежутке времени, попробуйте выставить больше лет для графиков"
return "Требуемый ежемесячный дивидендный результат будет достигнут через [ {} месяцев], при этом будет вложено: [ {}$ ], но ваш капитал достигнет к этому времени за счет сложного процента: [ {:.2f}$ ]".format(result['month'], result['current_capital_no_reinv'], result['current_capital_with_all_reinv'])
""" Var in input field might be not floar, but empty or string, in such case use default value """
def input_to_float(var, default):
if var.isdigit():
return float(var)
else:
return default
@app.callback(
[Output(component_id='dividends-graph',component_property='figure'),
Output(component_id='capital-graph',component_property='figure'),
Output(component_id='result', component_property='children')],
[Input(component_id='maximum-years', component_property='value'),
Input(component_id='divident-income-per-month', component_property='value'),
Input(component_id='start-capital', component_property='value'),
Input(component_id='regular-payment', component_property='value'),
Input(component_id='start-divident-percent', component_property='value'),
Input(component_id='average-cost-grow-percent', component_property='value')]
)
def update_output_div(maximum_years, divident_income_per_month, start_capital, regular_payment, start_divident_percent, average_cost_grow_percent):
max_years_number = int(maximum_years)
MONTH_COUNT_YEAR = 12
divident_income_per_month = input_to_float(divident_income_per_month, default__divident_income_per_month)
start_capital = input_to_float(start_capital, default__start_capital)
regular_payment = input_to_float(regular_payment, default__regular_payment)
start_divident_percent = input_to_float(start_divident_percent, default__start_divident_percent)
average_cost_grow_percent = input_to_float(average_cost_grow_percent, default__average_cost_grow_percent)
current_capital_no_reinv = current_capital_just_percent_reinv = current_capital_with_all_reinv = start_capital
info = {}
info['month'] = []
info['dividend_no_reinv'] = []
info['dividend_percent_reinv'] = []
info['dividend_all_reinv'] = []
info['cap_no_reinv'] = []
info['cap_percent_reinv'] = []
info['cap_all_reinv'] = []
target = {'month': 0, 'dividend': 0, 'current_capital_no_reinv': 0, 'current_capital_with_all_reinv': 0}
for month in range(max_years_number * MONTH_COUNT_YEAR):
info['month'].append(month)
current_capital_no_reinv += regular_payment
info['cap_no_reinv'].append(current_capital_no_reinv)
current_dividend_no_reinv = current_capital_no_reinv * start_divident_percent / 100 / MONTH_COUNT_YEAR
info['dividend_no_reinv'].append(current_dividend_no_reinv)
current_capital_just_percent_reinv = (current_capital_just_percent_reinv + regular_payment) * (1 + average_cost_grow_percent / 100 / MONTH_COUNT_YEAR)
info['cap_percent_reinv'].append(current_capital_just_percent_reinv)
current_dividend_just_percent_reinv = current_capital_just_percent_reinv * start_divident_percent / 100 / MONTH_COUNT_YEAR
info['dividend_percent_reinv'].append(current_dividend_just_percent_reinv)
current_dividend_with_all_reinv = current_capital_with_all_reinv * start_divident_percent / 100 / MONTH_COUNT_YEAR
info['dividend_all_reinv'].append(current_dividend_with_all_reinv)
current_capital_with_all_reinv = (current_capital_with_all_reinv + regular_payment + current_dividend_with_all_reinv) * (1 + average_cost_grow_percent / 100 / MONTH_COUNT_YEAR)
info['cap_all_reinv'].append(current_capital_with_all_reinv)
if((current_dividend_with_all_reinv >= divident_income_per_month) and not (target['month'])):
target['month'] = month
target['dividend'] = current_dividend_with_all_reinv
target['current_capital_no_reinv'] = current_capital_no_reinv
target['current_capital_with_all_reinv'] = current_capital_with_all_reinv
return create_dividends_graph(info, target, ''), create_capital_graph(info, target, ''), total_result_div(target)
Перезапускаем сервис, чтобы применить все изменения на веб сайте
# systemctl restart invests
Работа дивидендного калькулятора
Значения по-умолчанию для основных входных данных:
желаемый ежемесячный доход от дивидендов — 1000 долларов
стартовый капитал — 1000 долларов
ежемесячные пополнения брокерского счета для покупки дивидендных акций — 1000 долларов
средний процент дивидендов по акциям — 4%
средний рост цены дивидендных акций — 12.5% (на основе статистики по S&P Dividends aristocrats)
Все входные данные размещаются в редактируемых полях
Результаты можно увидеть на графиках ниже, куда поступают данные после обработки
график роста ежемесячных дивидендов:
a) получаемый за счет роста цены акций и ежемесячных ре-инвестирований дивидендов,
б) получаемый только за счет роста цены акций, т.е. если дивиденды будем выводить (без ре-инвестирования),
в) получаемый, если бы мы просто клали деньги «под подушку», без инвестирования, вообще
график роста капитала при тех же трех, рассматриваемых в первом пункте, условиях (а), б), в))
Бонусом, над графиками, представлен «ползунок» взгляда в будущее (изменяется в месяцах): что же произойдет с нашими дивидендами и капиталом, если продолжать вкладывать деньги следуя той же стратегии и далее
Итог
При взгляде на 2 графика: роста дивидендного дохода и роста капитала, можно сделать несколько интересных выводов:
значительно выгоднее вкладывать деньги в хорошие компании, чем просто хранить их
значительно выгоднее ре-инвестировать дивиденды
особенно, эффект заметен на горизонте более 10 лет
рост происходит экспоненциально
цифры по прошествии 20 лет и больше, даже, пугают
другие выводы можете сделать самостоятельно, «поиграв» с настройками, входными параметрами
Попадая в административную панель блога на вордпресс мы сразу же хотим создать свою первую статью. Я решил попробовать с приветственного слова.
Но, сперва, стоит внести простейшие изменения, чтобы ваш блог с первой статьей не был «Очередной сайт на WordPress»
Переходим в Настройки и вводим Заголовок вот какой нам понравится, и заполняем другие поля актуальными данными и сохраняем.
В разделе Страниц нам необходимо или же отредактировать единственную там опубликованные страницу (обычно там размещается информация об авторе блога или его компании) или же удалить ее.
Затем, в разделе Записи, выбираем первую статью, сгенерированную системой, нажимаем Изменить и описываем, например, что сподвигло вас начать вести этот блог. Сохраняем изменения и публикуем статью (совет: чаще сохранять изменения). Любуемся результатами.
По большему счету это все, если вы ведете блог только для себя или своей души. В противном же случае, желательно, провести, хотя бы минимальные работы по сео-оптимизации.
Рекомендую поставить plugin All In One SEO Pack, один из «топовых» расширений для WordPress по данной тематике (весь необходимый нам функционал размещен в бесплатной версии). Итак, заходим в раздел Плагины, нажимаем на кнопку Добавить новый и в строке поиска вводим «All In One SEO Pack»
Искомый плагин будет первым в списке, и в его карточке нажимаем кнопку Установить.
После этого, возвращаемся в раздел Плагины и для нашего плагина нажимает Активировать для его «включения».
Перейдем к общим настройкам SEO — там же нажимаем, соответсвенно, Настройки SEO.
Большинство настроек уже хорошо смотрятся со значениями по умолчанию. Стоит обратить внимание на следующие, отредактировав их:
Описание дом. страницы — указываем чуть более развернутое описание
Google Analytics ID — да-да, тут необходимо создать счетчик для гугл аналитики. Делается это несложно — процесс описан в одной из следующих статей (ссылка)
Исключить отслеживание пользователей — чтобы не влиять на статистику по сайту нашими проверками веб-страниц в блоге
После этих немногочисленных изменений в работе плагина, в самом низу списка, нажимаем кнопку Обновить настройки.
А, теперь, мы можем за-апгрейдить нашу первую статью-запись.
Возвращаемся в раздел редактирования Записей
При наведении на название статьи появляются элементы управления — выбираем Изменить.
Справа от самой Записи есть элементы управления. Из значимых для нас:
Постоянная ссылка — так как строка урла браузера больше дружит с латиницей (последствия систем кодировок), советую адрес ввести латинскими буквами, произведя транслитерацию в случае русского-буквенного предлагаемого урла
Рубрики — тоже советую этот инструмент, категоризируя свои статьи, например «administration», «code», «books», «uncategorized», и другие
Метки — указываем ключевые тэги (это так же помогаем категоризировать наши статьи, но в другом срезе, а, кроме того, создает новые страницы в нашем блоге — страницы со статьями по определенному тегу, что положительно влияет на сео)
Последний важный момент — скролим в самый низ нашей статьи до раздела All In One SEO Pack и заполняем поля:
Заголовок — указываем краткий, но емкий заголовок для это статьи
Описание — указываем более развернутое описание
Чуть выше отображается «сниппет» — как будет выглядеть интерпритация страницы статьи в поисковиках.
Последний раз сохраняем и нажимаем кнопку Обновить, чтобы опубликовать изменения.